package com.ys.service.storage.impl;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.math.BigDecimal;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.amazon.SellingPartnerAPIAA.LWAAuthorizationCredentials;
import com.amazon.SellingPartnerAPIAA.LWAException;
import com.bo.sellingpartnerapi.Fulfillmentinboundv0.model.*;
import com.bo.sellingpartnerapi.Fulfillmentinboundv0.model.Address;
import com.google.gson.annotations.SerializedName;
import com.ys.config.MyConfig;
import com.ys.entity.base.TbPlatform;
import com.ys.entity.business.TpAmazonShop;
import com.ys.entity.business.TpAmazonShopProduct;
import com.ys.entity.logistics.TpAmazonAddress;
import com.ys.entity.storage.*;
import com.ys.entity.sys.TsUserChange;
import com.ys.enume.advanced.MarketplaceEnum;
import com.ys.enume.storage.TccFbaBoxUpItemEnum;
import com.ys.enume.storage.TccFbaDeliverEnum;
import com.ys.enume.storage.TccFbaLogisticsMethodEnum;
import com.ys.enume.storage.TccFbaPlanEnum;
import com.ys.mapper.business.TpAmazonShopProductMapper;
import com.ys.mapper.storage.*;
import com.ys.service.log.ApiLogService;
import com.ys.service.storage.FbaInboundApiService;
import com.ys.service.storage.TccFbaBoxUpService;
import com.ys.service.sys.PdfService;
import com.ys.util.AESUtil;
import com.ys.util.RedisUtil;
import com.ys.util.ToolUtil;
import com.ys.util.amazon.FbaInboundApiV0;
import com.ys.util.amazon.Helper;
import com.ys.util.amazon.SellerSecretsVO;
import com.ys.util.dhecp.DateUtils;
import com.ys.util.shiro.ShiroUtils;
import com.ys.vo.R;
import io.swagger.client.ApiException;
import io.swagger.client.api.FbaInboundApi;
import io.swagger.client.model.*;
import io.swagger.client.model.Currency;
import io.swagger.client.model.Dimensions;
import io.swagger.client.model.PrepOwner;
import io.swagger.client.model.UnitOfMeasurement;
import io.swagger.client.model.UnitOfWeight;
import io.swagger.client.model.Weight;
import org.jboss.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.threeten.bp.OffsetDateTime;
import org.threeten.bp.temporal.ChronoUnit;

import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @Author: fxz
 * @CreateTime: 2024-12-12
 * @Description: 亚马逊货件API
 * @Version: 1.5
 */
@Service("fbaInboundApiService")
public class FbaInboundApiServiceImpl implements FbaInboundApiService {
    private static final Logger logger = Logger.getLogger(FbaInboundApiServiceImpl.class);

    //FBA名称
    private static final String FBAINBOUNDAPI = "FBAINBOUNDAPI";

    @Autowired
    private FbaInboundApiMapper fbaInboundApiMapper;

    @Autowired
    private TccFbaInboundApiLogMapper tccFbaInboundApiLogMapper;

    @Autowired
    private TccFbaPlanMapper tccFbaPlanMapper;

    @Autowired
    private TccFbaBoxUpService tccFbaBoxUpService;

    @Autowired
    private TccFbaBoxUpInfoMapper tccFbaBoxUpInfoMapper;

    @Autowired
    private TccFbaBoxUpMapper tccFbaBoxUpMapper;

    @Autowired
    private PdfService pdfService;

    @Autowired
    private StorageMapper storageMapper;

    @Autowired
    private TpAmazonShopProductMapper tpAmazonShopProductMapper;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private TccFbaDeliverItemMapper tccFbaDeliverItemMapper;


    /**
     * 按箱发货
     * @param tccFbaPlan
     * @return
     */
    @Override
    public R boxDelivery(TccFbaPlan tccFbaPlan) {
        int k = 0;
        List<Map<String, Object>> tccFbaPlanItemMap = null;
        while (true) {
            try {
                if (k == 0) {
                    tccFbaPlanItemMap = fbaInboundApiMapper.getTccFbaPlanItemHb(tccFbaPlan.getBid());
                    if (tccFbaPlanItemMap == null) {
                        return R.error("FBA计划详情不存在!");
                    }
                }

                //获取店铺信息
                JSONObject tpAmazonShop = getTpAmazonShop(tccFbaPlan.getShopId());
                if (tpAmazonShop == null) {
                    return R.error("网店信息不存在!");
                }
                FbaInboundApi fbaInboundApi = getFbaInboundApi(tpAmazonShop);
                if (fbaInboundApi == null) {
                    return R.error("亚马逊token不存在!");
                }

                CreateInboundPlanRequest body = new CreateInboundPlanRequest();
                //添加国家
                List<String> destinationMarketplaces = new ArrayList();
                destinationMarketplaces.add(tpAmazonShop.get("marketplaceId").toString());
                body.setDestinationMarketplaces(destinationMarketplaces);
                //计划需要的商品信息
                List<ItemInput> items = new ArrayList();
                for (Map<String, Object> tccFbaPlanItem : tccFbaPlanItemMap) {
                    ItemInput itemInput = new ItemInput();

                    if (tccFbaPlanItem.get("labelOwner").toString().equals("SELLER")){
                        itemInput.setLabelOwner(LabelOwner.SELLER);
                    }else {
                        itemInput.setLabelOwner(LabelOwner.NONE);
                    }
                    if (tccFbaPlanItem.get("prepOwner").toString().equals("SELLER")){
                        itemInput.setPrepOwner(PrepOwner.SELLER);
                    }else {
                        itemInput.setPrepOwner(PrepOwner.NONE);
                    }

//                    if (tccFbaPlanItem.get("fnsku").toString().indexOf("B") == 0) {
//                        //无需包装
//                        itemInput.setLabelOwner(LabelOwner.NONE);
//                    } else {
//                        //我们自己打包产品（贴标签）
//                        itemInput.setLabelOwner(LabelOwner.SELLER);
//                    }
//                    String[] prepInstructionList = tccFbaPlanItem.get("prepInstructionList").toString().split(",");
//                    if (prepInstructionList.length == 1 && prepInstructionList[0].equals("Labeling")) {
//                        itemInput.setPrepOwner(PrepOwner.NONE);
//                    } else {
//                        //特殊产品 的包装 承诺是自己包装)
//                        itemInput.setPrepOwner(PrepOwner.SELLER);
//                    }

                    //发货的sku数量 最小1最大10000
                    if (new Integer(tccFbaPlanItem.get("numPlanDeliver").toString()) > 10000) {
                        return R.error("SKU:" + tccFbaPlanItem.get("SKU").toString() + ",最大数量不允许超过10000个");
                    }
                    itemInput.setQuantity(new Integer(tccFbaPlanItem.get("numApiDeliver").toString()));
                    //sku
                    itemInput.setMsku(tccFbaPlanItem.get("sku").toString());
                    items.add(itemInput);
                }
                body.setItems(items);
                //计划名称，不传默认
//            body.setName("bid");

                //发货地址
                AddressInput sourceAddress = new AddressInput();
                //地址1
                sourceAddress.setAddressLine1(tpAmazonShop.get("addressLine1").toString());
                if (tpAmazonShop.get("addressLine2") != null && !tpAmazonShop.get("addressLine2").equals("")) {
                    //地址2
                    sourceAddress.setAddressLine2(tpAmazonShop.get("addressLine2").toString());
                }
                //城市
                sourceAddress.setCity(tpAmazonShop.get("city").toString());
                //国家 默认是cn
                sourceAddress.setCountryCode("CN");
                //姓名
                sourceAddress.setName(tpAmazonShop.get("name").toString());
                //手机
                sourceAddress.setPhoneNumber(tpAmazonShop.get("phone").toString());
                //邮编
                sourceAddress.setPostalCode(tpAmazonShop.get("postalCode").toString());
                //州
                sourceAddress.setStateOrProvinceCode(tpAmazonShop.get("stateOrProvinceCode").toString());

                body.setSourceAddress(sourceAddress);

                //创建货件单
                CreateInboundPlanResponse inboundPlan = fbaInboundApi.createInboundPlan(body);
                logger.info("inboundPlan成功!:" + JSONArray.toJSONString(inboundPlan));

                TccFbaInboundApiLog tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("createInboundPlan", tccFbaPlan.getId().toString(), tccFbaPlan.getBid(),
                        JSONArray.toJSONString(body), JSONArray.toJSONString(inboundPlan), 1);
                tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);

                R r = getInboundOperationStatusList(inboundPlan.getOperationId(), fbaInboundApi);
                if (r.getCode() != 0) {
                    tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("getInboundOperationStatus", tccFbaPlan.getId().toString(), tccFbaPlan.getBid(),
                            inboundPlan.getOperationId(), r.getMsg(), 1);
                    tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                    logger.error("createInboundPlan创建失败原因如下:" + r.getMsg());
                    redisUtil.delete(tccFbaPlan.getBid());
                    if (r.getMsg().equals("ERROR: This product has a maximum inventory level and exceeds the allowed quantity. View the maximum inventory level on the Restock Inventory page.")){
                        return R.error("计划审核失败,失败原因如下:超过最大库存数量,请至亚马逊后台核实最大库存!");
                    }
//                    return R.error("计划审核失败,失败原因如下:" + r.getMsg());
                    return R.error("计划审核失败,失败原因如下:请至亚马逊后台对应的sku操作预处理!");
                }


                //生成入站计划的可用包装选项
                GeneratePackingOptionsResponse generatePackingOptionsResponse = fbaInboundApi.generatePackingOptions(inboundPlan.getInboundPlanId());
                logger.info("generatePackingOptions成功!:" + JSONArray.toJSONString(generatePackingOptionsResponse));
                tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("generatePackingOptions", tccFbaPlan.getId().toString(), tccFbaPlan.getBid(),
                        inboundPlan.getInboundPlanId(), JSONArray.toJSONString(generatePackingOptionsResponse), 1);
                tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);

                r = getInboundOperationStatusList(generatePackingOptionsResponse.getOperationId(), fbaInboundApi);
                if (r.getCode() != 0) {
                    tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("getInboundOperationStatusPackingOptions", tccFbaPlan.getId().toString(), tccFbaPlan.getBid(),
                            generatePackingOptionsResponse.getOperationId(), r.getMsg(), 1);
                    tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                    logger.error("generatePackingOptions生成失败原因如下:" + r.getMsg());
                    redisUtil.delete(tccFbaPlan.getBid());
                    return R.error("计划审核失败,失败原因如下:" + r.getMsg());
                }

                //获取包装组信息
                ListPackingOptionsResponse listPackingOptionsResponse = fbaInboundApi.listPackingOptions(inboundPlan.getInboundPlanId(), null, null);
                logger.info("listPackingOptions成功!:" + JSONArray.toJSONString(listPackingOptionsResponse));
                tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("listPackingOptions", tccFbaPlan.getId().toString(), tccFbaPlan.getBid(),
                        inboundPlan.getInboundPlanId(), JSONArray.toJSONString(listPackingOptionsResponse), 1);
                tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                //测试数据代码
//            CreateInboundPlanResponse inboundPlan = new CreateInboundPlanResponse();
//            inboundPlan.setInboundPlanId("wfd6c4844a-225d-4ad0-adda-7ea816c1f68c");
//            TccFbaInboundApiLog tccFbaInboundApiLog = new TccFbaInboundApiLog().setType("listPackingOptions").queryFirst();
//            JSONObject resultJO = JSON.parseObject(tccFbaInboundApiLog.getJsonResult());
//            ListPackingOptionsResponse listPackingOptionsResponse = JSON.parseObject(JSON.toJSONString(resultJO),ListPackingOptionsResponse.class);
//            R r;
                //获取对应包装组的明细
                if (listPackingOptionsResponse != null) {
                    List<TccFbaPlanItem> tccFbaPlanItemList = new TccFbaPlanItem().setBidFbaPlan(tccFbaPlan.getBid()).queryList();
                    List<Item> itemNew = null;
                    List<TccFbaBoxUpByAdd> tccFbaBoxUpByAddList = new ArrayList<>();
                    TccFbaBoxUpByAdd tccFbaBoxUpByAdd = new TccFbaBoxUpByAdd();
                    List<TccFbaBoxUpInfoByAdd> tccFbaBoxUpInfoByAdds = new ArrayList<>();
                    PackingOption packingOption = listPackingOptionsResponse.getPackingOptions().get(0);
                    if (packingOption.getPackingGroups().size() > 1){
                        logger.error("PackingGroups包装组多个----分仓:" + tccFbaPlan.getBid());
                        redisUtil.delete(tccFbaPlan.getBid());
                        return R.error("计划审核失败,失败原因如下:该计划已被分仓!");
                    }
                    for (String packingGroupId : packingOption.getPackingGroups()) {
                        //测试数据代码
//                    TccFbaInboundApiLog listPackingGroupItemsLog = new TccFbaInboundApiLog().setType("listPackingGroupItems").queryFirst();
//                    JSONObject resultJO123 = JSON.parseObject(listPackingGroupItemsLog.getJsonResult());
//                    ListPackingGroupItemsResponse listPackingGroupItemsResponse = JSON.parseObject(JSON.toJSONString(resultJO123),ListPackingGroupItemsResponse.class);

                        ListPackingGroupItemsResponse listPackingGroupItemsResponse = fbaInboundApi.listPackingGroupItems(inboundPlan.getInboundPlanId(),
                                packingGroupId, null, null);
                        logger.info("listPackingGroupItems成功!:" + JSONArray.toJSONString(listPackingGroupItemsResponse));
                        tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("listPackingGroupItems", tccFbaPlan.getId().toString(), tccFbaPlan.getBid(),
                                packingGroupId, JSONArray.toJSONString(listPackingGroupItemsResponse), 1);
                        tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);

                        TccFbaBoxUpInfoByAdd tccFbaBoxUpInfoByAdd = new TccFbaBoxUpInfoByAdd();
                        tccFbaBoxUpInfoByAdd.setPackId(packingOption.getPackingOptionId());
                        tccFbaBoxUpInfoByAdd.setPackToken(packingGroupId);
                        List<TccFbaBoxUpItemByAdd> tccFbaBoxUpItemByAdds = new ArrayList<>();

                        for (TccFbaPlanItem tccFbaPlanItem : tccFbaPlanItemList) {
                            itemNew = listPackingGroupItemsResponse.getItems().stream().filter(item -> item.getAsin().equals(tccFbaPlanItem.getAsin())
                                    && item.getFnsku().equals(tccFbaPlanItem.getFnSku())
                                    && item.getMsku().equals(tccFbaPlanItem.getSku()))
                                    .collect(Collectors.toList());
                            Item item = itemNew.get(0);
                            //新增装箱明细
                            TccFbaBoxUpItemByAdd tccFbaBoxUpItemByAdd = new TccFbaBoxUpItemByAdd();
                            tccFbaBoxUpItemByAdd.setFbaPlanItemId(tccFbaPlanItem.getId());
                            tccFbaBoxUpItemByAdd.setAsin(item.getAsin());
                            tccFbaBoxUpItemByAdds.add(tccFbaBoxUpItemByAdd);
                        }
                        tccFbaBoxUpInfoByAdd.setGoodsInfoList(tccFbaBoxUpItemByAdds);
                        tccFbaBoxUpInfoByAdds.add(tccFbaBoxUpInfoByAdd);
                        tccFbaBoxUpByAdd.setFbaOrPackInfoList(tccFbaBoxUpInfoByAdds);
                        tccFbaBoxUpByAdd.setPlacementOptionId(packingOption.getPackingOptionId());
                    }
                    tccFbaBoxUpByAddList.add(tccFbaBoxUpByAdd);

                    //选择包装选项
                    ConfirmPackingOptionResponse confirmPackingOptionResponse = fbaInboundApi.confirmPackingOption(
                            inboundPlan.getInboundPlanId(), packingOption.getPackingOptionId());
                    logger.info("confirmPackingOption成功!:" + JSONArray.toJSONString(confirmPackingOptionResponse));
                    tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("confirmPackingOption", tccFbaPlan.getId().toString(), tccFbaPlan.getBid(),
                            packingOption.getPackingOptionId(), JSONArray.toJSONString(confirmPackingOptionResponse), 1);
                    tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);

                    r = getInboundOperationStatusList(confirmPackingOptionResponse.getOperationId(), fbaInboundApi);
                    if (r.getCode() != 0) {
                        tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("getInboundOperationStatusCpo", tccFbaPlan.getId().toString(), tccFbaPlan.getBid(),
                                confirmPackingOptionResponse.getOperationId(), r.getMsg(), 1);
                        tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                        logger.error("confirmPackingOption设置包装选项失败原因如下:" + r.getMsg());
                        redisUtil.delete(tccFbaPlan.getBid());
                        return R.error("计划审核失败,失败原因如下:" + r.getMsg());
                    }

                    //获取制单人信息
                    TsUserChange tsUserChange = new TsUserChange().setUserId(ShiroUtils.getUserId()).setStatus(1).queryFirst();
                    String auditingUser = null;
                    Date auditingTime = null;
                    if (tsUserChange != null) {
                        auditingUser = tsUserChange.getUserId() + '/' + tsUserChange.getUserName();
                        auditingTime = new Date();
                    } else {
                        return R.error("未查询到制单人信息！");
                    }
                    tccFbaPlan.setAuditingUser(auditingUser);
                    tccFbaPlan.setAuditingTime(auditingTime);
                    //保存inboundPlanId逻辑
                    tccFbaPlan.setInboundPlanId(inboundPlan.getInboundPlanId());
                    tccFbaPlan.setStatus(TccFbaPlanEnum.Status.ISAUDITED.value);
                    tccFbaPlanMapper.update(tccFbaPlan);

                    //新增装箱数据
                    r = tccFbaBoxUpService.addOneFbaBoxInfo(tccFbaBoxUpByAddList, tccFbaPlan.getBid());
                    if (r.getCode() != 0) {
                        return R.error(r.getMsg());
                    }
                    if (k != 0){
                        //回填Amazon商品的值
                        for (Map<String, Object> map : tccFbaPlanItemMap) {
                            TpAmazonShopProduct tpAmazonShopProduct = new TpAmazonShopProduct().setId(Long.valueOf(map.get("id").toString())).queryFirst();
                            tpAmazonShopProduct.setLabelOwner(map.get("labelOwner").toString());
                            tpAmazonShopProduct.setPrepOwner(map.get("prepOwner").toString());
                            tpAmazonShopProductMapper.update(tpAmazonShopProduct);
                        }
                    }

                    return R.ok();
                }
            } catch (ApiException e) {
                k = k + 1;
                if (k > 1){
                    logger.error("计划审核失败原因如下:" + e.getResponseBody());
                    redisUtil.delete(tccFbaPlan.getBid());
                    return R.error("API接口访问失败,具体原因,请联系客服!");
                }
                Boolean falx = true;
                JSONObject getData = JSONObject.parseObject(e.getResponseBody());
                JSONArray details = JSONArray.parseArray(getData.get("errors").toString());
                if (details != null && details.size() > 0) {
                    for (int i = 0; i < details.size(); i++) {
                        JSONObject jsonObjectData = (JSONObject) details.get(i);
                        if (jsonObjectData.get("message").toString().contains("prepOwner")) {
                            for (Map<String, Object> map : tccFbaPlanItemMap) {
                                if (jsonObjectData.get("message").toString().contains(map.get("sku").toString())) {
                                    map.put("prepOwner", "SELLER");
                                    falx = false;
                                }
                            }
                        }
                        if (jsonObjectData.get("message").toString().contains("labelOwner")) {
                            for (Map<String, Object> map : tccFbaPlanItemMap) {
                                if (jsonObjectData.get("message").toString().contains(map.get("sku").toString())) {
                                    map.put("labelOwner", "SELLER");
                                    falx = false;
                                }
                            }
                        }
                    }
                }
                if (falx){
                    logger.error("计划审核失败原因如下:" + e.getResponseBody());
                    redisUtil.delete(tccFbaPlan.getBid());
                    return R.error("API接口访问失败,具体原因,请联系客服!");
                }
            } catch (Exception e) {
                logger.error("计划审核失败原因如下:" + e.getMessage());
                redisUtil.delete(tccFbaPlan.getBid());
                return R.error(e.getMessage());
            }
        }
    }

    /**
     * 按SUK发货
     * @param tccFbaPlan
     * @return
     */
    @Override
    public R skuDelivery(TccFbaPlan tccFbaPlan) {
        try {
            List<Map<String, Object>> tccFbaPlanItemMap = fbaInboundApiMapper.getTccFbaPlanItemHb(tccFbaPlan.getBid());
            if (tccFbaPlanItemMap == null){
                return R.error("FBA计划详情不存在!");
            }

            //获取店铺信息
            JSONObject tpAmazonShop = getTpAmazonShop(tccFbaPlan.getShopId());
            if (tpAmazonShop == null){
                return R.error("网店信息不存在!");
            }
            FbaInboundApi fbaInboundApi = getFbaInboundApi(tpAmazonShop);
            if (fbaInboundApi == null){
                return R.error("亚马逊token不存在!");
            }

            CreateInboundPlanRequest body = new CreateInboundPlanRequest();
            //添加国家
            List<String> destinationMarketplaces = new ArrayList();
            destinationMarketplaces.add(tpAmazonShop.get("marketplaceId").toString());
            body.setDestinationMarketplaces(destinationMarketplaces);
            //计划需要的商品信息
            List<ItemInput> items = new ArrayList();
            for (Map<String, Object> tccFbaPlanItem : tccFbaPlanItemMap) {
                ItemInput itemInput = new ItemInput();
                if (tccFbaPlanItem.get("fnsku").toString().indexOf("B") == 0 ){
                    //无需包装
                    itemInput.setLabelOwner(LabelOwner.NONE);
                }else {
                    //我们自己打包产品（贴标签）
                    itemInput.setLabelOwner(LabelOwner.SELLER);
                }
                String[] prepInstructionList = tccFbaPlanItem.get("prepInstructionList").toString().split(",");
                if (prepInstructionList.length == 1  && prepInstructionList[0].equals("Labeling")){
                    itemInput.setPrepOwner(PrepOwner.NONE);
                }else {
                    //特殊产品 的包装 承诺是自己包装)
                    itemInput.setPrepOwner(PrepOwner.SELLER);
                }
                //发货的sku数量 最小1最大10000
                if (new Integer(tccFbaPlanItem.get("numPlanDeliver").toString()) > 10000){
                    return R.error("SKU:" +tccFbaPlanItem.get("SKU").toString()  + ",最大数量不允许超过10000个");
                }
                itemInput.setQuantity(new Integer(tccFbaPlanItem.get("numPlanDeliver").toString()));
                //sku
                itemInput.setMsku(tccFbaPlanItem.get("sku").toString());
                items.add(itemInput);
            }
            body.setItems(items);
            //计划名称，不传默认
            body.setName("bid");

            //发货地址
            AddressInput sourceAddress = new AddressInput();
            //地址1
            sourceAddress.setAddressLine1(tpAmazonShop.get("addressLine1").toString());
            //地址2
            sourceAddress.setAddressLine2(tpAmazonShop.get("addressLine2").toString());
            //城市
            sourceAddress.setCity(tpAmazonShop.get("city").toString());
            //国家 默认是cn
            sourceAddress.setCountryCode("CN");
            //姓名
            sourceAddress.setName(tpAmazonShop.get("name").toString());
            //手机
            sourceAddress.setPhoneNumber(tpAmazonShop.get("phone").toString());
            //邮编
            sourceAddress.setPostalCode(tpAmazonShop.get("postalCode").toString());
            //州
            sourceAddress.setStateOrProvinceCode(tpAmazonShop.get("stateOrProvinceCode").toString());

            //创建货件单
            CreateInboundPlanResponse inboundPlan = fbaInboundApi.createInboundPlan(body);
            logger.info("inboundPlan成功!:" + JSONArray.toJSONString(inboundPlan));

            TccFbaInboundApiLog tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("createInboundPlan",tccFbaPlan.getId().toString(),tccFbaPlan.getBid(),
                    JSONArray.toJSONString(body), JSONArray.toJSONString(inboundPlan), 1);
            tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);

            R r = getInboundOperationStatusList(inboundPlan.getOperationId(),fbaInboundApi);
            if (r.getCode() != 0){
                tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("getInboundOperationStatus",tccFbaPlan.getId().toString(),tccFbaPlan.getBid(),
                        inboundPlan.getOperationId(), r.getMsg(), 1);
                tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                logger.error("createInboundPlan创建失败原因如下:" + r.getMsg());
                return R.error("计划审核失败,失败原因如下:" + r.getMsg());
            }

            tccFbaPlan.setInboundPlanId(inboundPlan.getInboundPlanId());
            tccFbaPlanMapper.update(tccFbaPlan);

            //设置放置选项generatePackingOptions
            GeneratePlacementOptionsResponse generatePlacementOptionsResponse = fbaInboundApi.generatePlacementOptions(inboundPlan.getInboundPlanId(),new GeneratePlacementOptionsRequest());
            tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("generatePlacementOptions",tccFbaPlan.getId().toString(),tccFbaPlan.getBid(),
                    JSONArray.toJSONString(inboundPlan.getInboundPlanId()), JSONArray.toJSONString(generatePlacementOptionsResponse), 1);
            tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
            logger.info("generatePlacementOptions成功!:" + JSONArray.toJSONString(generatePlacementOptionsResponse));

            r = getInboundOperationStatusList(generatePlacementOptionsResponse.getOperationId(),fbaInboundApi);
            if (r.getCode() != 0){
                tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("getInboundOperationStatusPlacementOptions",tccFbaPlan.getId().toString(),tccFbaPlan.getBid(),
                        generatePlacementOptionsResponse.getOperationId(), r.getMsg(), 1);
                tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                logger.error("generatePlacementOptions生成失败原因如下:" + r.getMsg());
                return R.error("计划审核失败,失败原因如下:" + r.getMsg());
            }

            //获取放置选项
            ListPlacementOptionsResponse listPlacementOptionsResponse = fbaInboundApi.listPlacementOptions(inboundPlan.getInboundPlanId(), null, null);
            tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("listPlacementOptions",tccFbaPlan.getId().toString(),tccFbaPlan.getBid(),
                    inboundPlan.getInboundPlanId(), JSONArray.toJSONString(listPlacementOptionsResponse), 1);
            tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
            logger.info("listPlacementOptions成功!:" + JSONArray.toJSONString(listPlacementOptionsResponse));

            for (PlacementOption placementOption :  listPlacementOptionsResponse.getPlacementOptions()){
                //查询货件详情
                for (String shipmentId : placementOption.getShipmentIds()){
                    Shipment shipment = fbaInboundApi.getShipment(inboundPlan.getInboundPlanId(), shipmentId);
                    tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("getShipment",shipmentId,tccFbaPlan.getBid(),
                            shipmentId, JSONArray.toJSONString(shipment), 1);
                    tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                    logger.info("getShipment成功!:" + JSONArray.toJSONString(shipment));

                    //                    获取每一个FBA里面的具体商品信息
                    ListShipmentItemsResponse listShipmentItemsResponse = fbaInboundApi.listShipmentItems(tccFbaPlan.getInboundPlanId(), shipmentId,null,null);
                    tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("listShipmentItems",shipmentId,tccFbaPlan.getBid(),
                            shipmentId, JSONArray.toJSONString(listShipmentItemsResponse), 1);
                    tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                    logger.info("listShipmentItems成功!:" + JSONArray.toJSONString(listShipmentItemsResponse));
                }
            }
            return R.ok();
        }catch (ApiException e){
            logger.error("计划审核失败原因如下:" + e.getResponseBody());
            return R.error(e.getResponseBody());
        }catch (Exception e){
            logger.error("计划审核失败原因如下:" + e.getMessage());
            return R.error(e.getMessage());
        }
    }

    /**
     * 按SUK发货 - 货件预览  TODO 测试 正式删除代码
     * @param
     * @return
     */
    @Override
    public R searchFlow(String bid) {
//        List<TccFbaShipmentPreview> tccFbaShipmentPreviewList = new ArrayList<>();
//        for (int j = 1; j < 4; j++) {
//            if (j == 1){
//                for (int i = 0; i < 5; i++) {
//                    TccFbaShipmentPreview tccFbaShipmentPreview = new TccFbaShipmentPreview();
//                    tccFbaShipmentPreview.setRadioNum(j);
//                    tccFbaShipmentPreview.setShippingSolution(5 + "个货件");
//                    tccFbaShipmentPreview.setFee(BigDecimal.ZERO);
//                    tccFbaShipmentPreview.setFbaName("FBA"+new Random().nextInt() +new Random().nextInt()+new Random().nextInt()+new Random().nextInt());
//                    tccFbaShipmentPreview.setPlacementOptionId("pl5c5b8a95-de27-43d4-9a51-38c1407600be"+new Random().nextInt());
//                    tccFbaShipmentPreview.setShipmentId("shd3b4d3f0-c8e5-4ba7-9563-d1c3a0f06651"+new Random().nextInt());
//                    switch (i) {
//                        case 0:
//                            tccFbaShipmentPreview.setWarehouseId("FTW1");
//                            break;
//                        case 1:
//                            tccFbaShipmentPreview.setWarehouseId("MQJ1");
//                            break;
//                        case 2:
//                            tccFbaShipmentPreview.setWarehouseId("SMF3");
//                            break;
//                        case 3:
//                            tccFbaShipmentPreview.setWarehouseId("AVP1");
//                            break;
//                        case 4:
//                            tccFbaShipmentPreview.setWarehouseId("MEM1");
//                            break;
//                    }
//                    tccFbaShipmentPreviewList.add(tccFbaShipmentPreview);
//                }
//            }
//            if (j == 2){
//                for (int i = 0; i < 3; i++) {
//                    TccFbaShipmentPreview tccFbaShipmentPreview = new TccFbaShipmentPreview();
//                    tccFbaShipmentPreview.setRadioNum(j);
//                    tccFbaShipmentPreview.setShippingSolution(3 + "个货件");
//                    tccFbaShipmentPreview.setFee(new BigDecimal(26));
//                    tccFbaShipmentPreview.setFbaName("FBA"+new Random().nextInt() +new Random().nextInt()+new Random().nextInt()+new Random().nextInt());
//                    tccFbaShipmentPreview.setPlacementOptionId("pl5c5b8a95-de27-43d4-9a51-38c1407600be"+new Random().nextInt());
//                    tccFbaShipmentPreview.setShipmentId("shd3b4d3f0-c8e5-4ba7-9563-d1c3a0f06651"+new Random().nextInt());
//                    switch (i) {
//                        case 0:
//                            tccFbaShipmentPreview.setWarehouseId("LAN2");
//                            break;
//                        case 1:
//                            tccFbaShipmentPreview.setWarehouseId("BNA6");
//                            break;
//                        case 2:
//                            tccFbaShipmentPreview.setWarehouseId("ONTB");
//                            break;
//                    }
//                    tccFbaShipmentPreviewList.add(tccFbaShipmentPreview);
//                }
//            }
//            if (j == 3){
//                for (int i = 0; i < 2; i++) {
//                    TccFbaShipmentPreview tccFbaShipmentPreview = new TccFbaShipmentPreview();
//                    tccFbaShipmentPreview.setRadioNum(j);
//                    tccFbaShipmentPreview.setShippingSolution(2 + "个货件");
//                    tccFbaShipmentPreview.setFee(new BigDecimal(21));
//                    tccFbaShipmentPreview.setFbaName("FBA"+new Random().nextInt() +new Random().nextInt()+new Random().nextInt()+new Random().nextInt());
//                    tccFbaShipmentPreview.setPlacementOptionId("pl5c5b8a95-de27-43d4-9a51-38c1407600be"+new Random().nextInt());
//                    tccFbaShipmentPreview.setShipmentId("shd3b4d3f0-c8e5-4ba7-9563-d1c3a0f06651"+new Random().nextInt());
//                    switch (i) {
//                        case 0:
//                            tccFbaShipmentPreview.setWarehouseId("HGR6");
//                            break;
//                        case 1:
//                            tccFbaShipmentPreview.setWarehouseId("HIA1");
//                            break;
//                    }
//                    tccFbaShipmentPreviewList.add(tccFbaShipmentPreview);
//                }
//            }
//            if (j == 4){
//                for (int i = 0; i < 1; i++) {
//                    TccFbaShipmentPreview tccFbaShipmentPreview = new TccFbaShipmentPreview();
//                    tccFbaShipmentPreview.setRadioNum(j);
//                    tccFbaShipmentPreview.setShippingSolution(1 + "个货件");
//                    tccFbaShipmentPreview.setFee(new BigDecimal(33));
//                    tccFbaShipmentPreview.setFbaName("FBA"+new Random().nextInt() +new Random().nextInt()+new Random().nextInt()+new Random().nextInt());
//                    tccFbaShipmentPreview.setPlacementOptionId("pl5c5b8a95-de27-43d4-9a51-38c1407600be"+new Random().nextInt());
//                    tccFbaShipmentPreview.setWarehouseId("TMB8");
//                    tccFbaShipmentPreview.setShipmentId("shd3b4d3f0-c8e5-4ba7-9563-d1c3a0f06651"+new Random().nextInt());
//
//                    tccFbaShipmentPreviewList.add(tccFbaShipmentPreview);
//                }
//            }
//        }

        TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(bid).queryFirst();
        //正式切换代码
        List<TccFbaShipmentPreview> tccFbaShipmentPreviewList = new ArrayList<>();

        TccFbaInboundApiLog tccFbaInboundApiLog = new TccFbaInboundApiLog()
                .setPid(tccFbaPlan.getId().toString())
                .setBid(tccFbaPlan.getBid())
                .setType("listPlacementOptions")
                .queryFirst();
        if (tccFbaInboundApiLog != null){
            JSONObject resultJO = JSON.parseObject(tccFbaInboundApiLog.getJsonResult());
            JSONArray conditionJA = JSON.parseArray(resultJO.get("placementOptions").toString());
            BigDecimal fee = BigDecimal.ZERO;
            for (int i = 0; i < conditionJA.size(); i++) {
                JSONObject JO = conditionJA.getJSONObject(i);
                JSONArray shipmentIds = JSON.parseArray(JO.get("shipmentIds").toString());
                JSONArray fees = JSON.parseArray(JO.get("fees").toString());
                //查询货件详情
                for (int j = 0; j < shipmentIds.size(); j++) {
                    String  shipmentId = shipmentIds.get(j).toString();
                    TccFbaInboundApiLog shipmentLog = new TccFbaInboundApiLog()
                            .setPid(shipmentId)
                            .setBid(tccFbaPlan.getBid())
                            .setType("getShipment")
                            .queryFirst();
                    if (shipmentLog == null){
                        continue;
                    }
                    Shipment shipment = JSON.parseObject(shipmentLog.getJsonResult(), Shipment.class);

                    TccFbaShipmentPreview tccFbaShipmentPreview = new TccFbaShipmentPreview();
                    tccFbaShipmentPreview.setRadioNum(i);
                    tccFbaShipmentPreview.setShippingSolution(shipmentIds.size() + "个货件");
                    if (fees != null) {
                        for (int k = 0; k < fees.size(); k++) {
                            JSONObject feeJs = fees.getJSONObject(k);
                            if (feeJs.get("target").equals("Placement Services")){
                                JSONObject feeValue = JSON.parseObject(feeJs.get("value").toString());
                                if (feeValue.size() != 0){
                                    fee = new BigDecimal(feeValue.get("amount").toString());
                                }
                            }
                        }
                    }
                    tccFbaShipmentPreview.setFee(fee);
                    tccFbaShipmentPreview.setFbaName(shipment.getName());
                    tccFbaShipmentPreview.setPlacementOptionId(shipment.getPlacementOptionId());
                    tccFbaShipmentPreview.setShipmentId(shipment.getShipmentId());
                    tccFbaShipmentPreview.setWarehouseId(shipment.getDestination().getWarehouseId());
                    tccFbaShipmentPreviewList.add(tccFbaShipmentPreview);
                }
            }
        }

        return R.ok(tccFbaShipmentPreviewList);
    }

    /**
     *     按SUK发货-货件预览详情  TODO 测试 正式删除代码
     * @param
     * @return
     */
    @Override
    public R searchFlowDetail(String bid,String shipmentId) {
        List<TccFbaPlanItem> tccFbaPlanItemListDatail = new ArrayList<>();
        ListShipmentItemsResponse listShipmentItemsResponse;
        List<TccFbaPlanItem> tccFbaPlanItemListNew;
        try {
            TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(bid).queryFirst();

            TccFbaInboundApiLog tccFbaInboundApiLog = new TccFbaInboundApiLog()
                    .setPid(shipmentId)
                    .setBid(tccFbaPlan.getBid())
                    .setType("listShipmentItems")
                    .queryFirst();

            if (tccFbaInboundApiLog == null){
                //获取店铺信息
                JSONObject tpAmazonShop = getTpAmazonShop(tccFbaPlan.getShopId());

                FbaInboundApi fbaInboundApi = getFbaInboundApi(tpAmazonShop);

                //获取每一个FBA里面的具体商品信息
                listShipmentItemsResponse = fbaInboundApi.listShipmentItems(tccFbaPlan.getInboundPlanId(), shipmentId,null,null);
                tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("listShipmentItems",shipmentId,tccFbaPlan.getBid(),
                        JSONArray.toJSONString(shipmentId), JSONArray.toJSONString(listShipmentItemsResponse), 1);
                tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                logger.info("listShipmentItems成功!:" + JSONArray.toJSONString(listShipmentItemsResponse));
            }else {
                listShipmentItemsResponse = JSON.parseObject(tccFbaInboundApiLog.getJsonResult(), ListShipmentItemsResponse.class);
            }

            List<TccFbaPlanItem> tccFbaPlanItemList = new TccFbaPlanItem().setBidFbaPlan(tccFbaPlan.getBid()).queryList();

            for (Item item : listShipmentItemsResponse.getItems()){
                //查询出来商品信息
                tccFbaPlanItemListNew = tccFbaPlanItemList.stream().filter(tccFbaPlanItem -> item.getAsin().equals(tccFbaPlanItem.getAsin())
                        && item.getFnsku().equals(tccFbaPlanItem.getFnSku())
                        && item.getMsku().equals(tccFbaPlanItem.getSku()))
                        .collect(Collectors.toList());
                if (tccFbaPlanItemListNew.size() !=0){
                    tccFbaPlanItemListDatail.add(tccFbaPlanItemListNew.get(0));
                }
            }

        }catch (ApiException e){
            logger.error("货件预览详情失败!:" + JSONArray.toJSONString(e.getResponseBody()));
            return R.error(e.getResponseBody());
        }catch (Exception e){
            logger.error("货件预览详情失败!:" + JSONArray.toJSONString(e.getMessage()));
            return R.error(e.getMessage());
        }

        return R.ok(tccFbaPlanItemListDatail);


        //测试数据
//        List<TccFbaPlanItem> tccFbaPlanItemList = new TccFbaPlanItem().setBidFbaPlan(bid).queryList();

//        return R.ok(tccFbaPlanItemList);
    }

    /**
     * 取消货件
     * @param tccFbaPlan 计划单
     * @return
     */
    @Override
    public R cancelInboundPlan(TccFbaPlan tccFbaPlan) {

        try {
            String bid = tccFbaPlan.getBid();
            String id = tccFbaPlan.getId().toString();

            //获取店铺信息
            JSONObject tpAmazonShop = getTpAmazonShop(tccFbaPlan.getShopId());
            if (tpAmazonShop == null){
                return R.error("网店信息不存在!");
            }
            FbaInboundApi fbaInboundApi = getFbaInboundApi(tpAmazonShop);
            if (fbaInboundApi == null){
                return R.error("亚马逊token不存在!");
            }

            //取消货件单
            CancelInboundPlanResponse cancelInboundPlanResponse = fbaInboundApi.cancelInboundPlan(tccFbaPlan.getInboundPlanId());
            logger.info("cancelInboundPlan成功!:" + JSONArray.toJSONString(cancelInboundPlanResponse));
            TccFbaInboundApiLog tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("cancelInboundPlan",id,bid,
                    tccFbaPlan.getInboundPlanId(), JSONArray.toJSONString(cancelInboundPlanResponse), 1);
            tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);

            InboundOperationStatus inboundOperationStatus = fbaInboundApi.getInboundOperationStatus(cancelInboundPlanResponse.getOperationId());
            if (inboundOperationStatus.getOperationStatus() != OperationStatus.SUCCESS){
                tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("cancelInboundPlanStatus",id,bid,
                        cancelInboundPlanResponse.getOperationId(), JSONArray.toJSONString(inboundOperationStatus), 1);
                tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                logger.error("cancelInboundPlan取消失败原因如下:" + inboundOperationStatus.getOperationProblems().get(0).getMessage());
                return R.error("取消计划失败,失败原因如下:" + inboundOperationStatus.getOperationProblems().get(0).getMessage());
            }
        }catch (ApiException e){
            logger.error("计划取消失败原因如下:" + e.getResponseBody());
            return R.error(e.getResponseBody());
        }catch (Exception e){
            logger.error("计划取消失败原因如下:" + e.getMessage());
            return R.error(e.getMessage());
        }
        return R.ok();
    }


    /**
     * 货件放置选项
     * @param tccFbaBoxUp
     * @return
     */
    @Override
    public R generatePlacementOptions(TccFbaBoxUp tccFbaBoxUp,int generateNo) {
        TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(tccFbaBoxUp.getBidFbaPlan()).queryFirst();
        try {
            //获取店铺信息
            JSONObject tpAmazonShop = getTpAmazonShop(tccFbaPlan.getShopId());
            if (tpAmazonShop == null){
                tccFbaPlan.setApiGetStatus(TccFbaPlanEnum.ApiGetStatus.FAIL.value);//API获取成功与否标识
                tccFbaPlanMapper.update(tccFbaPlan);
                return R.error("网店信息不存在!");
            }
            FbaInboundApi fbaInboundApi = getFbaInboundApi(tpAmazonShop);
            if (fbaInboundApi == null){
                tccFbaPlan.setApiGetStatus(TccFbaPlanEnum.ApiGetStatus.FAIL.value);//API获取成功与否标识
                tccFbaPlanMapper.update(tccFbaPlan);
                return R.error("亚马逊token不存在!");
            }

            //设置放置选项
            GeneratePlacementOptionsResponse generatePlacementOptionsResponse = fbaInboundApi.generatePlacementOptions(tccFbaPlan.getInboundPlanId(),new GeneratePlacementOptionsRequest());
            TccFbaInboundApiLog tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("generatePlacementOptions-"+generateNo,tccFbaPlan.getId().toString(),tccFbaPlan.getBid(),
                    tccFbaPlan.getInboundPlanId(), JSONArray.toJSONString(generatePlacementOptionsResponse), 1);
            tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
            logger.info("generatePlacementOptions成功!:" + JSONArray.toJSONString(generatePlacementOptionsResponse));

            R r = getInboundOperationStatusListNoWait(generatePlacementOptionsResponse.getOperationId(),fbaInboundApi);
            if (r.getCode() != 0){
                tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("getInboundOperationStatusPlacementOptions-"+generateNo,tccFbaPlan.getId().toString(),tccFbaPlan.getBid(),
                        generatePlacementOptionsResponse.getOperationId(), r.getMsg(), 1);
                tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                tccFbaPlan.setApiGetStatus(TccFbaPlanEnum.ApiGetStatus.FAIL.value);//API获取成功与否标识
                tccFbaPlanMapper.update(tccFbaPlan);
                logger.error("generatePlacementOptions生成失败原因如下:" + r.getMsg());
                return R.error("货件放置选项失败,失败原因如下:" + r.getMsg());
            }

            //获取放置选项
            ListPlacementOptionsResponse listPlacementOptionsResponse = fbaInboundApi.listPlacementOptions(tccFbaPlan.getInboundPlanId(), null, null);
            tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("listPlacementOptions-"+generateNo,tccFbaPlan.getId().toString(),tccFbaPlan.getBid(),
                    JSONArray.toJSONString(tccFbaPlan.getInboundPlanId()), JSONArray.toJSONString(listPlacementOptionsResponse), 1);
            tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
            logger.info("listPlacementOptions成功!:" + JSONArray.toJSONString(listPlacementOptionsResponse));

            for (PlacementOption placementOption :  listPlacementOptionsResponse.getPlacementOptions()){
                //查询货件详情
                for (String shipmentId : placementOption.getShipmentIds()){
                    Shipment shipment = fbaInboundApi.getShipment(tccFbaPlan.getInboundPlanId(), shipmentId);
                    //tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("getShipment",shipmentId,tccFbaBoxUp.getBid(),
                            //shipmentId, JSONArray.toJSONString(shipment), 1);

                    tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("getShipment-"+generateNo,shipmentId,tccFbaPlan.getBid(),
                            shipmentId, JSONArray.toJSONString(shipment), 1);
                    tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                    logger.info("getShipment成功!:" + JSONArray.toJSONString(shipment));
                    //destination FBA仓库地址
                    //warehouseId FBA仓库
                    //shipmentConfirmationId FBA编号
                    //amazonReferenceId FBA追踪编号



                    //class Shipment {
                    //    amazonReferenceId: null
                    //    contactInformation: null
                    //    dates: null
                    //    destination: class ShipmentDestination {
                    //        address: class Address {
                    //            addressLine1: Plot 1, Lyons Park,
                    //            addressLine2: Sayer Dr
                    //            city: Coventry
                    //            companyName: null
                    //            countryCode: GB
                    //            email: null
                    //            name: Amazon EU SARL (UK)
                    //            phoneNumber: null
                    //            postalCode: CV5 9PF
                    //            stateOrProvinceCode: West Midlands
                    //        }
                    //        destinationType: AMAZON_WAREHOUSE
                    //        warehouseId: BHX4
                    //    }
                    //    freightInformation: null
                    //    name: null
                    //    placementOptionId: pl5c5b8a95-de27-43d4-9a51-38c1407600be
                    //    selectedDeliveryWindow: null
                    //    selectedTransportationOptionId: null
                    //    selfShipAppointmentDetails: null
                    //    shipmentConfirmationId: null
                    //    shipmentId: shd3b4d3f0-c8e5-4ba7-9563-d1c3a0f06651
                    //    source: class ShipmentSource {
                    //        address: class Address {
                    //            addressLine1: WAN AN JIE DAO QUAN ZHOU SILU DIAN ZI SHANGWU YOUXIAN GONGSI
                    //            addressLine2: YANG GUANG GUO JI GUANG CHANG 2HAO LOU 2106
                    //            city: QUAN ZHOU SHI
                    //            companyName: null
                    //            countryCode: CN
                    //            email: null
                    //            name: SILULCM
                    //            phoneNumber: 15280576826
                    //            postalCode: 362010
                    //            stateOrProvinceCode: FU JIAN SHENG
                    //        }
                    //        sourceType: SELLER_FACILITY
                    //    }
                    //    status: UNCONFIRMED
                    //    trackingDetails: null
                    //}

                    //获取每一个FBA里面的具体商品信息
                    ListShipmentItemsResponse listShipmentItemsResponse = fbaInboundApi.listShipmentItems(tccFbaPlan.getInboundPlanId(), shipmentId,null,null);
                    tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("listShipmentItems-"+generateNo,shipmentId,tccFbaPlan.getBid(),
                            shipmentId, JSONArray.toJSONString(listShipmentItemsResponse), 1);
                    tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                    logger.info("listShipmentItems成功!:" + JSONArray.toJSONString(listShipmentItemsResponse));

                        //通过这几个参数
//                    private String asin = null; //asin
//                    private String fnsku = null; //fnsku
//                    private String msku = null; //sku
//                    private Integer quantity = null; 数量



                }
            }


        }catch (ApiException e){
            if(new TccFbaPlan().setBid(tccFbaPlan.getBid()).queryFirst().getGenerateNo() == generateNo){
                tccFbaPlan.setApiGetStatus(TccFbaPlanEnum.ApiGetStatus.FAIL.value);//API获取成功与否标识
                tccFbaPlanMapper.update(tccFbaPlan);
            }
            logger.error("货件放置选项失败原因如下:" + e.getResponseBody());
            return R.error(e.getResponseBody());
        }catch (Exception e){
            if(new TccFbaPlan().setBid(tccFbaPlan.getBid()).queryFirst().getGenerateNo() == generateNo){
                tccFbaPlan.setApiGetStatus(TccFbaPlanEnum.ApiGetStatus.FAIL.value);//API获取成功与否标识
                tccFbaPlanMapper.update(tccFbaPlan);
            }
            logger.error("货件放置选项失败原因如下:" + e.getMessage());
            return R.error(e.getMessage());
        }
        if(new TccFbaPlan().setBid(tccFbaPlan.getBid()).queryFirst().getGenerateNo() == generateNo){
            tccFbaPlan.setApiGetStatus(TccFbaPlanEnum.ApiGetStatus.SUCCESS.value);//API获取成功与否标识
            tccFbaPlanMapper.update(tccFbaPlan);
        }

        return R.ok();
    }

    /**
     * 提供方框内容信息(如有) 装箱信息
     * @param tccFbaBoxUp
     * @return
     */
    @Override
    public R setPackingInformation(TccFbaBoxUp tccFbaBoxUp) {
        try {
            SetPackingInformationRequest body = new SetPackingInformationRequest();
            TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(tccFbaBoxUp.getBidFbaPlan()).queryFirst();

            //获取店铺信息
            JSONObject tpAmazonShop = getTpAmazonShop(tccFbaPlan.getShopId());
            if (tpAmazonShop == null){
                return R.error("网店信息不存在!");
            }
            FbaInboundApi fbaInboundApi = getFbaInboundApi(tpAmazonShop);
            if (fbaInboundApi == null){
                return R.error("亚马逊token不存在!");
            }

            //包装组信息
            List<PackageGroupingInput> packageGroupings = new ArrayList();

            List<TccFbaBoxUp> boxUpList = new TccFbaBoxUp().setBidFbaPlan(tccFbaPlan.getBid()).queryList();

            //获取箱规信息
            List<TccFbaBox> boxList = new TccFbaBox()
                    //.setBidBoxUp(tccFbaBoxUp.getBid())
                    .addLeftJoin("TCC_FbaBoxUp B ON B.Bid = A.BidBoxUp")
                    .where("B.BidFbaPlan = '"+tccFbaPlan.getBid()+"'")
                    .queryList();


            //获取子列表信息
            List<TccFbaPlanItem> planItemList = new TccFbaPlanItem().setBidFbaPlan(tccFbaPlan.getBid()).queryList();
            List<Map<String,Object>> boxUpItemList = new TccFbaBoxUpItem()
                    .addLeftJoin("TCC_FbaPlanItem B ON B.Id = A.FbaPlanItemId")
                    .addField("B.Sku AS sku")
                    .setBidFbaPlan(tccFbaPlan.getBid())
                    .queryMap();
            //获取 装箱单FBA信息表
            List<TccFbaBoxUpInfo> boxUpInfoList = new TccFbaBoxUpInfo()
                    .addLeftJoin("TCC_FbaBoxUp B ON B.Bid = A.BoxUpBid")
                    .where("B.BidFbaPlan = '"+tccFbaPlan.getBid()+"'")
                    .queryList();

            for(TccFbaBoxUp boxUp:boxUpList){
                String boxUpBid = boxUp.getBid();
                //箱规信息
                List<TccFbaBox> boxListByUpBid = boxList.stream().filter(e->e.getBidBoxUp().equals(boxUpBid)).collect(Collectors.toList());


                //高
                BigDecimal height = BigDecimal.ZERO;
                //长
                BigDecimal length = BigDecimal.ZERO;
                //宽
                BigDecimal width = BigDecimal.ZERO;
                //重量
                BigDecimal boxWeight = BigDecimal.ZERO;
                UnitOfMeasurement unitOfMeasurement = null;
                UnitOfWeight unit = null;
                //箱子数据
                List<BoxInput> boxInputs = new ArrayList<>();
                for (TccFbaBox tcFbaBox:boxListByUpBid) {
                    //欧洲 || 其他国家
                    if (!tpAmazonShop.get("amazonRegionCode").toString().equals("EUROPE")){
                        height = tcFbaBox.getBoxHigh().multiply(new BigDecimal(0.3937008)).setScale(2, BigDecimal.ROUND_HALF_UP);
                        length = tcFbaBox.getBoxLong().multiply(new BigDecimal(0.3937008)).setScale(2, BigDecimal.ROUND_HALF_UP);
                        width = tcFbaBox.getBoxWide().multiply(new BigDecimal(0.3937008)).setScale(2, BigDecimal.ROUND_HALF_UP);
                        boxWeight = tcFbaBox.getBoxWeight().multiply(new BigDecimal(2.205)).setScale(2, BigDecimal.ROUND_HALF_UP);
                        unitOfMeasurement = UnitOfMeasurement.IN;
                        unit = UnitOfWeight.LB;
                    }else {
                        height = tcFbaBox.getBoxHigh();
                        length = tcFbaBox.getBoxLong();
                        width = tcFbaBox.getBoxWide();
                        boxWeight = tcFbaBox.getBoxWeight();
                        unitOfMeasurement = UnitOfMeasurement.CM;
                        unit = UnitOfWeight.KG;
                    }
                    BoxInput boxInput = new BoxInput();
                    //箱子信息有卖家提供的二维码提供
                    boxInput.setContentInformationSource(BoxContentInformationSource.BOX_CONTENT_PROVIDED);
                    //包装尺寸
                    Dimensions dimensions = new Dimensions();
                    //高
                    dimensions.setHeight(height);
                    //长
                    dimensions.setLength(length);
                    //宽
                    dimensions.setWidth(width);
                    //厘米
                    dimensions.setUnitOfMeasurement(unitOfMeasurement);
                    boxInput.setDimensions(dimensions);

                    //重量
                    Weight weight = new Weight();
                    weight.setUnit(unit);
                    weight.setValue(boxWeight);
                    boxInput.setWeight(weight);

                    //数量
                    boxInput.setQuantity(1);

                    int creationMethod = tccFbaPlan.getCreationMethod();//下单方式(0.手动|1.自动)

                    List<ItemInput> items = new ArrayList<>();
                    if(creationMethod == 1 && tccFbaPlan.getEvenlyBoxNum()!=null && tccFbaPlan.getEvenlyBoxNum()>=5){
                        Map<String, List<Map<String, Object>>> groupsBySku = boxUpItemList.stream().collect(Collectors.groupingBy(e->e.get("sku").toString()));
                        groupsBySku.forEach((sku, groupListBySku) -> {
                            //计划单单子列表
                            TccFbaPlanItem planItem = planItemList.stream()
                                    .filter(e->e.getId().equals(Long.parseLong(groupListBySku.get(0).get("fbaPlanItemId").toString())))
                                    .collect(Collectors.toList()).get(0);
                            //获取网店商品信息
                            TpAmazonShopProduct tpAmazonShopProduct = new TpAmazonShopProduct().setId(planItem.getAmazonShopProductId()).queryFirst();
                            //计划需要的商品信息
                            ItemInput itemInput = new ItemInput();
                            if (tpAmazonShopProduct.getLabelOwner().equals("SELLER")){
                                itemInput.setLabelOwner(LabelOwner.SELLER);
                            }else {
                                itemInput.setLabelOwner(LabelOwner.NONE);
                            }
                            if (tpAmazonShopProduct.getPrepOwner().equals("SELLER")){
                                itemInput.setPrepOwner(PrepOwner.SELLER);
                            }else {
                                itemInput.setPrepOwner(PrepOwner.NONE);
                            }

                            int num = 0;
                            for(Map<String, Object> item:groupListBySku){
                                num = num + Integer.parseInt(item.get("averageBoxUpNum").toString());
                            }

                            itemInput.setQuantity(num);
                            //sku
                            itemInput.setMsku(sku);
                            items.add(itemInput);

                        });


                    }else{
                        List<Map<String,Object>> boxDetailList = new TccFbaBoxDetail()
                                .addLeftJoin("TCC_FbaBoxUp B ON B.Bid = A.BidBoxUp")
                                .where("B.BidFbaPlan = '"+tccFbaPlan.getBid()+"'")
                                .addLeftJoin("TCC_FbaBoxUpItem C ON C.Id = A.BoxUpItemId")
                                .addField("C.AverageBoxUpNum AS averageBoxUpNum")
                                .addLeftJoin("TCC_FbaPlanItem D ON C.FbaPlanItemId = D.Id")
                                .addField("D.Sku AS sku")
                                .queryMap();
                        List<Map<String,Object>> boxDetailListByUpBidAndBoxId = boxDetailList.stream()
                                .filter(e->e.get("bidBoxUp").toString().equals(boxUpBid) && Long.parseLong(e.get("boxId").toString())==tcFbaBox.getId())
                                .collect(Collectors.toList());

                        //根据sku 分组
                        Map<String, List<Map<String, Object>>> groupsByStr = boxDetailListByUpBidAndBoxId.stream().collect(Collectors.groupingBy(e->e.get("sku").toString()));

                        //遍历，分组的信息
                        groupsByStr.forEach((sku, groupListBySku) -> {
                            Map<String, Object> groupListBySkuOne = groupListBySku.get(0);
                            //获取子列表信息
                            //装箱单子列表
                            Map<String, Object> boxUpItem = boxUpItemList.stream()
                                    .filter(e->Long.parseLong(e.get("id").toString()) == Long.parseLong(groupListBySkuOne.get("boxUpItemId").toString()))
                                    .collect(Collectors.toList()).get(0);
                            //计划单单子列表
                            TccFbaPlanItem planItem = planItemList.stream()
                                    .filter(e->e.getId().equals(Long.parseLong(boxUpItem.get("fbaPlanItemId").toString())))
                                    .collect(Collectors.toList()).get(0);
                            //获取网店商品信息
                            TpAmazonShopProduct tpAmazonShopProduct = new TpAmazonShopProduct().setId(planItem.getAmazonShopProductId()).queryFirst();
                            //计划需要的商品信息
                            ItemInput itemInput = new ItemInput();
                            if (tpAmazonShopProduct.getLabelOwner().equals("SELLER")){
                                itemInput.setLabelOwner(LabelOwner.SELLER);
                            }else {
                                itemInput.setLabelOwner(LabelOwner.NONE);
                            }
                            if (tpAmazonShopProduct.getPrepOwner().equals("SELLER")){
                                itemInput.setPrepOwner(PrepOwner.SELLER);
                            }else {
                                itemInput.setPrepOwner(PrepOwner.NONE);
                            }
                            int num = 0;

//                            if(creationMethod == 1 && tccFbaPlan.getEvenlyBoxNum()!=null && tccFbaPlan.getEvenlyBoxNum()>=5){
//                                List<Map<String, Object>> boxUpItemListBySku =boxUpItemList.stream().filter(e->e.get("sku").toString().equals(sku)).collect(Collectors.toList());
//                                for(Map<String, Object> item:boxUpItemListBySku){
//                                    num = num + Integer.parseInt(item.get("averageBoxUpNum").toString());
//                                }
//                            }else {
//                                for(Map<String,Object> info:groupListBySku){
//                                    num = num + Integer.parseInt(info.get("num").toString());
//                                }
//                            }
                            for(Map<String,Object> info:groupListBySku){
                                num = num + Integer.parseInt(info.get("num").toString());
                            }

                            itemInput.setQuantity(num);
                            //sku
                            itemInput.setMsku(sku);
                            items.add(itemInput);
                        });
                    }


                    boxInput.setItems(items);
                    boxInputs.add(boxInput);
                }

                {

                    PackageGroupingInput packageGroupingInput = new PackageGroupingInput();
                    //shipmentId按SKU发货  packingGroupId按箱发货  只能选择一个 包装id
                    if(tccFbaPlan.getDeliverState()==1){//发货计划（1按SKU自动发货，0按箱自动发货）
                        //获取 装箱单FBA信息表
                        List<TccFbaBoxUpInfo> boxUpInfoListByUpBid = boxUpInfoList.stream()
                                .filter(e->e.getBoxUpBid().equals(boxUpBid))
                                .collect(Collectors.toList());
                        TccFbaBoxUpInfo tccFbaBoxUpInfo = boxUpInfoListByUpBid.get(0);
                        packageGroupingInput.setShipmentId(tccFbaBoxUpInfo.getFbaNo());
                    }else {
                        packageGroupingInput.setPackingGroupId(tccFbaBoxUp.getPackToken());
                    }
                    packageGroupingInput.setBoxes(boxInputs);
                    packageGroupings.add(packageGroupingInput);
                }


            }

            body.setPackageGroupings(packageGroupings);

            //上传装箱数据
            SetPackingInformationResponse setPackingInformationResponse = fbaInboundApi.setPackingInformation(tccFbaPlan.getInboundPlanId(), body);
            TccFbaInboundApiLog tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("setPackingInformation",tccFbaPlan.getId().toString(),tccFbaPlan.getBid(),
                    tccFbaPlan.getInboundPlanId(), JSONArray.toJSONString(setPackingInformationResponse), 1);
            tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
            logger.info("setPackingInformation成功!:" + JSONArray.toJSONString(setPackingInformationResponse));

            R r = getInboundOperationStatusList(setPackingInformationResponse.getOperationId(),fbaInboundApi);
            if (r.getCode() != 0){
                tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("getInboundOperationStatusPackingInformation",tccFbaPlan.getId().toString(),tccFbaPlan.getBid(),
                        setPackingInformationResponse.getOperationId(), r.getMsg(), 1);
                tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                logger.error("setPackingInformationResponse上传箱子信息失败原因如下:" +  r.getMsg());
                return R.error("上传箱子信息失败,失败原因如下:" + r.getMsg());
            }

        }catch (ApiException e){
            logger.error("提供装箱信息失败原因如下:" + e.getResponseBody(), e.getResponseBody(),e);
            return R.error(e.getResponseBody());
        }catch (Exception e){
            logger.error("提供装箱信息失败原因如下:" + e.getMessage(), e.getMessage(),e);
            return R.error(e.getMessage());
        }
        return R.ok();
    }


    /**
     * 手动通过fba编号获取fba信息
     * @param tccFbaBoxUp
     * @param shipmentId
     * @return
     */
    @Override
    public R getShipments(TccFbaBoxUp tccFbaBoxUp, String shipmentId) {
        ConfirmTransportationOptionsRequest body = new ConfirmTransportationOptionsRequest();
        TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(tccFbaBoxUp.getBidFbaPlan()).queryFirst();

        //获取店铺信息
        JSONObject tpAmazonShop = getTpAmazonShop(tccFbaPlan.getShopId());
        if (tpAmazonShop == null){
            return R.error("网店信息不存在!");
        }
        FbaInboundApiV0 fbaInboundApiV0 = getFbaInboundApiV0(tpAmazonShop);
        if (fbaInboundApiV0 == null){
            return R.error("亚马逊token不存在!");
        }

        try {
            List<String> shipmentIdList = new ArrayList<>();
            shipmentIdList.add(shipmentId);
            GetShipmentsResponse getShipmentsResponse = fbaInboundApiV0.getShipments("SHIPMENT", tpAmazonShop.get("sellerId").toString(),
                    null, shipmentIdList, null, null, null);
            logger.info("fbaInboundApiV0-getShipments成功!:" + JSONArray.toJSONString(getShipmentsResponse));
            TccFbaInboundApiLog tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("fbaInboundApiV0-getShipments",tccFbaBoxUp.getId().toString(),tccFbaBoxUp.getBid(),
                    shipmentId, JSONArray.toJSONString(getShipmentsResponse), 1);
            tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);

            GetShipmentItemsResponse getShipmentItemsResponse = fbaInboundApiV0.getShipmentItemsByShipmentId(shipmentId, tpAmazonShop.get("sellerId").toString());
            logger.info("fbaInboundApiV0-getShipmentItemsResponse成功!:" + JSONArray.toJSONString(getShipmentItemsResponse));
            tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("fbaInboundApiV0-getShipmentItemsResponse",tccFbaBoxUp.getId().toString(),tccFbaBoxUp.getBid(),
                    shipmentId, JSONArray.toJSONString(getShipmentsResponse), 1);
            tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);

            GetShipmentItemsResult getShipmentItemsResult = getShipmentItemsResponse.getPayload();
            //去重亚马逊条数
            Set<String> setItem = new HashSet<>();

            for (InboundShipmentItem itemData : getShipmentItemsResult.getItemData()) {
                setItem.add(itemData.getSellerSKU());
            }

            TccFbaBoxUpInfo tccFbaBoxUpInfoByCheck = new TccFbaBoxUpInfo().setBoxUpBid(tccFbaBoxUp.getBid()).setFbaNo(shipmentId).queryFirst();
            List<TccFbaPlanItem> itemList = new TccFbaPlanItem()
                    .addLeftJoin("TCC_FbaBoxUpItem B ON B.FbaPlanItemId = A.Id")
                    .addLeftJoin("TCC_FbaBoxDetail C ON C.BoxUpItemId = B.Id")
                    .where("C.FbaBoxUpInfoId = "+tccFbaBoxUpInfoByCheck.getId())
                    .where("B.BidBoxUp = '"+tccFbaBoxUp.getBid()+"'")
                    .queryList();

            //去重
            Map<String, List<TccFbaPlanItem>> groupsByStr = itemList.stream().collect(Collectors.groupingBy(e->e.getSku()));
            //去重erp商品条数
            Set<String> setErp = new HashSet<>();
            //遍历，填入去重的信息
            groupsByStr.forEach((k, v) -> setErp.add(k));

            boolean comarry = comarry(setErp, setItem);
            if (!comarry) {
                logger.error("FBA导入"+shipmentId+"失败,商品信息不匹配!");
                return R.error("FBA导入"+shipmentId+"失败,商品信息不匹配!");
            }

            GetShipmentsResult payload1 = getShipmentsResponse.getPayload();

            List<TccFbaBoxUpInfo> tccFbaBoxUpInfoList = new TccFbaBoxUpInfo().setBoxUpBid(tccFbaBoxUp.getBid()).queryList();
            for (InboundShipmentInfo inboundShipmentInfo : payload1.getShipmentData()) {
//                inboundShipmentInfo.getShipmentId() fba编号 FbaId
//                inboundShipmentInfo.getDestinationFulfillmentCenterId() 仓库标识 FbaWarehouse
//                inboundShipmentInfo.getShipFromAddress() 仓库地址
                for(TccFbaBoxUpInfo tccFbaBoxUpInfo:tccFbaBoxUpInfoList){
                    if(tccFbaBoxUpInfo.getFbaNo().equals(shipmentId)){
                        tccFbaBoxUpInfo.setFbaWarehouse(inboundShipmentInfo.getDestinationFulfillmentCenterId());//仓库标识
                        //仓库地址
                        Address address = inboundShipmentInfo.getShipFromAddress();
                        //拼接仓库地址
                        String fbaWarehouseAddr = address.getPostalCode();
                        int creationMethod = tccFbaPlan.getCreationMethod();//下单方式(0.手动|1.自动)
                        if(creationMethod==0){//手动
                            TpAmazonAddress tpAmazonAddress = new TpAmazonAddress().setDestinationFulfillmentCenterId(inboundShipmentInfo.getDestinationFulfillmentCenterId()).queryFirst();
                            if(tpAmazonAddress!=null && tpAmazonAddress.getId()!=null){
                                fbaWarehouseAddr = tpAmazonAddress.getPostalCode();
                            }else {
                                return R.error("仓库标识：" + inboundShipmentInfo.getDestinationFulfillmentCenterId()+"在亚马逊仓库地址管理中未维护!");
                            }
                        }
//                        String fbaWarehouseAddr = address.getName()
//                                + address.getAddressLine1()
//                                + address.getAddressLine2()
//                                + address.getDistrictOrCounty()
//                                + address.getCity()
//                                + address.getStateOrProvinceCode()
//                                + address.getCountryCode()
//                                + address.getPostalCode();
                        //获取FBA费用
                        tccFbaBoxUpInfo.setFbaWarehouseAddr(fbaWarehouseAddr);
                        BoxContentsFeeDetails boxContentsFeeDetails = inboundShipmentInfo.getEstimatedBoxContentsFee();
                        if(boxContentsFeeDetails!=null){
                            Amount amount = boxContentsFeeDetails.getTotalFee();
                            tccFbaBoxUpInfo.setFbaAmount(amount.getValue());
                        }

                        tccFbaBoxUpInfoMapper.update(tccFbaBoxUpInfo);
                    }
                }
            }

        } catch (com.bo.sellingpartnerapi.Authorization.invoker.ApiException e) {
            logger.error("获取FBA信息失败原因如下:" + e.getResponseBody(),e.getMessage(),e);
            return R.error(e.getResponseBody());
        }catch (Exception e) {
            logger.error("获取FBA信息失败原因如下:" + e.getMessage(),e.getMessage(),e);
            return R.error(e.getMessage());
        }
        return R.ok();
    }

    /**
     * 请求api设置放置选项
     * @param tccFbaPlan
     * @return
     */
    @Override
    public R confirmPlacementOption(TccFbaPlan tccFbaPlan,String placementOptionId) {

        try {
            //获取店铺信息
            JSONObject tpAmazonShop = getTpAmazonShop(tccFbaPlan.getShopId());
            if (tpAmazonShop == null){
                return R.error("网店信息不存在!");
            }
            List<TccFbaPlanItem> tccFbaPlanItemList = new TccFbaPlanItem().setBidFbaPlan(tccFbaPlan.getBid()).queryList();

            List<TccFbaPlanItem> tccFbaPlanItemListNew ;

            FbaInboundApi fbaInboundApi = getFbaInboundApi(tpAmazonShop);
            if (fbaInboundApi == null){
                return R.error("亚马逊token不存在!");
            }

            //获取放置选项
            TccFbaInboundApiLog listPlacementOptionsLog = new TccFbaInboundApiLog()
                .setPid(tccFbaPlan.getId().toString())
                .setBid(tccFbaPlan.getBid())
                .setType("listPlacementOptions")
                .queryFirst();

            JSONObject resultJO = JSON.parseObject(listPlacementOptionsLog.getJsonResult());
            JSONArray conditionJA = JSON.parseArray(resultJO.get("placementOptions").toString());
            BigDecimal fee = BigDecimal.ZERO;
            for (int i = 0; i < conditionJA.size(); i++) {
                JSONObject JO = conditionJA.getJSONObject(i);
                JSONArray shipmentIds = JSON.parseArray(JO.get("shipmentIds").toString());
                JSONArray fees = JSON.parseArray(JO.get("fees").toString());
                if (JO.get("placementOptionId").toString().equals(placementOptionId)){
                    //每一个货件就是一个装箱单
                    for (int j = 0; j < shipmentIds.size(); j++) {
                        String  shipmentId = shipmentIds.get(j).toString();
                        //货件信息
                        TccFbaInboundApiLog getShipmentLog = new TccFbaInboundApiLog()
                                .setPid(shipmentId)
                                .setBid(tccFbaPlan.getBid())
                                .setType("getShipment")
                                .queryFirst();

                        Shipment shipment = JSON.parseObject(getShipmentLog.getJsonResult(), Shipment.class);

                        //货件详情
                        TccFbaInboundApiLog listShipmentItemsLog = new TccFbaInboundApiLog()
                                .setPid(shipmentId)
                                .setBid(tccFbaPlan.getBid())
                                .setType("listShipmentItems")
                                .queryFirst();

                        ListShipmentItemsResponse listShipmentItemsResponse = JSON.parseObject(listShipmentItemsLog.getJsonResult(), ListShipmentItemsResponse.class);

                        List<TccFbaBoxUpItemByAdd> tccFbaBoxUpItemByAdds = new ArrayList<>();
                        for (Item item : listShipmentItemsResponse.getItems()){
                            tccFbaPlanItemListNew = tccFbaPlanItemList.stream().filter(tccFbaPlanItem -> item.getAsin().equals(tccFbaPlanItem.getAsin())
                                    && item.getFnsku().equals(tccFbaPlanItem.getFnSku())
                                    && item.getMsku().equals(tccFbaPlanItem.getSku()))
                                    .collect(Collectors.toList());
                            if(tccFbaPlanItemListNew.size() == 0){
                                continue;
                            }
                            TccFbaPlanItem tccFbaPlanItem = tccFbaPlanItemListNew.get(0);
                            //新增装箱明细

                            /*
                            TccFbaBoxUpItemByAdd tccFbaBoxUpItemByAdd = new TccFbaBoxUpItemByAdd();
                            //shipmentConfirmationId FBA编号
                            tccFbaBoxUpItemByAdd.setFbaNo(shipment.getShipmentConfirmationId());
                            //amazonReferenceId FBA追踪编号
                            tccFbaBoxUpItemByAdd.setFbaTrackNo(shipment.getAmazonReferenceId());
                            tccFbaBoxUpItemByAdd.setFbaToken(null);
                            tccFbaBoxUpItemByAdd.setFbaId(shipmentId);
                            if (shipment.getDestination() != null){
                                //warehouseId FBA仓库
                                tccFbaBoxUpItemByAdd.setFbaWarehouse(shipment.getDestination().getWarehouseId());
                                if (shipment.getDestination().getAddress() != null){
                                    io.swagger.client.model.Address address = shipment.getDestination().getAddress();
                                    //destination FBA仓库地址
                                    String fbaWarehouseAddr = address.getPostalCode();
//                                    String fbaWarehouseAddr = address.getName()
//                                            + address.getAddressLine1()
//                                            + address.getAddressLine2()
//                                            + address.getCity()
//                                            + address.getStateOrProvinceCode()
//                                            + address.getCountryCode()
//                                            + address.getPostalCode();
                                    tccFbaBoxUpItemByAdd.setFbaWarehouseAddr(fbaWarehouseAddr);
                                }
                            }
                            if (fees != null) {
                                for (int k = 0; k < fees.size(); k++) {
                                    JSONObject feeJs = fees.getJSONObject(k);
                                    if (feeJs.get("target").equals("Placement Services")){
                                        JSONObject feeValue = JSON.parseObject(feeJs.get("value").toString());
                                        if (feeValue.size() != 0){
                                            fee = new BigDecimal(feeValue.get("amount").toString());
                                        }
                                    }
                                }
                            }
                            tccFbaBoxUpItemByAdd.setFbaAmount(fee);
                            tccFbaBoxUpItemByAdd.setFbaPlanItemId(tccFbaPlanItem.getId());
                            tccFbaBoxUpItemByAdd.setAsin(tccFbaPlanItem.getAsin());
                            tccFbaBoxUpItemByAdd.setBoxUpNum(item.getQuantity());
                            tccFbaBoxUpItemByAdd.setPlacementOptionId(placementOptionId);
                            tccFbaBoxUpItemByAdds.add(tccFbaBoxUpItemByAdd);
                            */
                        }
                        //新增装箱数据
                        //R r = tccFbaBoxUpService.addOneFbaBoxInfo(tccFbaBoxUpItemByAdds,tccFbaPlan.getBid());


                        R r = R.ok();


                        if (r.getCode() != 0){
                            return R.error(r.getMsg());
                        }
                    }
                }
            }

            //获取制单人信息
            TsUserChange tsUserChange = new TsUserChange().setUserId(ShiroUtils.getUserId()).setStatus(1).queryFirst();
            String auditingUser = null;
            Date auditingTime = null;
            if(tsUserChange!=null){
                auditingUser = tsUserChange.getUserId() + '/' + tsUserChange.getUserName();
                auditingTime = new Date();
            }else {
                return R.error("未查询到制单人信息！");
            }
            tccFbaPlan.setAuditingUser(auditingUser);
            tccFbaPlan.setAuditingTime(auditingTime);
            tccFbaPlan.setStatus(TccFbaPlanEnum.Status.ISAUDITED.value);
            tccFbaPlanMapper.update(tccFbaPlan);

//            //只能使用一个配置placementOptionId 选择放置选项
//            ConfirmPlacementOptionResponse confirmPlacementOptionResponse = fbaInboundApi.confirmPlacementOption(tccFbaPlan.getInboundPlanId(),
//                    placementOptionId);
//            logger.info("confirmPlacementOption成功!:" + JSONArray.toJSONString(confirmPlacementOptionResponse));
//
//            TccFbaInboundApiLog tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("confirmPlacementOption",tccFbaPlan.getId().toString(),tccFbaPlan.getBid(),
//                    JSONArray.toJSONString(placementOptionId), JSONArray.toJSONString(confirmPlacementOptionResponse), 1);
//            tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
//
//            InboundOperationStatus inboundOperationStatus = fbaInboundApi.getInboundOperationStatus(confirmPlacementOptionResponse.getOperationId());
//            if (inboundOperationStatus.getOperationStatus() != OperationStatus.SUCCESS){
//                tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("confirmPlacementOptionStatus",tccFbaPlan.getId().toString(),tccFbaPlan.getBid(),
//                        JSONArray.toJSONString(confirmPlacementOptionResponse.getOperationId()), JSONArray.toJSONString(inboundOperationStatus), 1);
//                tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
//                logger.error("confirmPlacementOption失败原因如下:" + inboundOperationStatus.getOperationProblems().get(0).getMessage());
//                return R.error("计划审核失败,失败原因如下:" + inboundOperationStatus.getOperationProblems().get(0).getMessage());
//            }
            return R.ok();
        //}catch (ApiException e){
            //logger.error("计划审核失败原因如下:" + e.getResponseBody());
            //return R.error(e.getResponseBody());
        }catch (Exception e){
            logger.error("计划审核失败原因如下:" + e.getMessage());
            return R.error(e.getMessage());
        }
    }

    /**
     * 请求api设置放置选项
     * @param tccFbaBoxUp
     * @return
     */
    @Override
    public R fbaBoxConfirmPlacementOption(TccFbaBoxUp tccFbaBoxUp,String placementOptionId) {
        try {

            TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(tccFbaBoxUp.getBidFbaPlan()).queryFirst();
            //获取店铺信息
            JSONObject tpAmazonShop = getTpAmazonShop(tccFbaPlan.getShopId());
            if (tpAmazonShop == null){
                return R.error("网店信息不存在!");
            }

            FbaInboundApi fbaInboundApi = getFbaInboundApi(tpAmazonShop);
            if (fbaInboundApi == null){
                return R.error("亚马逊token不存在!");
            }

            //只能使用一个配置placementOptionId 选择放置选项
            ConfirmPlacementOptionResponse confirmPlacementOptionResponse = fbaInboundApi.confirmPlacementOption(tccFbaPlan.getInboundPlanId(),
                    placementOptionId);
            logger.info("confirmPlacementOption成功!:" + JSONArray.toJSONString(confirmPlacementOptionResponse));

            TccFbaInboundApiLog tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("confirmPlacementOption",tccFbaBoxUp.getId().toString(),tccFbaBoxUp.getBid(),
                    JSONArray.toJSONString(placementOptionId), JSONArray.toJSONString(confirmPlacementOptionResponse), 1);
            tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);



            ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
            AtomicInteger executionCount = new AtomicInteger(0);
            final int maxExecutions = 15; // 最大执行次数
            Runnable task = () -> {
                InboundOperationStatus inboundOperationStatus = null;
                try {
                    inboundOperationStatus = fbaInboundApi.getInboundOperationStatus(confirmPlacementOptionResponse.getOperationId());
                    if (inboundOperationStatus.getOperationStatus() != OperationStatus.SUCCESS){
                        TccFbaInboundApiLog tccFbaInboundApiLogByNew = TccFbaInboundApiLog.tccFbaInboundApiLog("confirmPlacementOptionStatus",tccFbaBoxUp.getId().toString(),tccFbaBoxUp.getBid(),
                                JSONArray.toJSONString(confirmPlacementOptionResponse.getOperationId()), JSONArray.toJSONString(inboundOperationStatus), 1);
                        tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLogByNew);
                        logger.error("confirmPlacementOption失败原因如下:" + inboundOperationStatus.getOperationProblems());
                    }
                    logger.info("执行的次数:" + executionCount.incrementAndGet());
                    if (executionCount.get() >= maxExecutions || inboundOperationStatus.getOperationStatus() == OperationStatus.SUCCESS) {
                        scheduler.shutdown(); // 关闭执行器，停止所有任务
                    }
                } catch (ApiException e) {
                    logger.error("请求api设置放置选项失败原因如下:" + e.getResponseBody(),e.getResponseBody(),e);
                } catch (LWAException e) {
                    logger.error("请求api设置放置选项失败原因如下:" + e.getMessage(),e.getMessage(),e);
                }

            };

            // 在0秒后启动任务, 每1秒执行一次
            scheduler.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS);


            //storageMapper.updateBoxUpPlacementOptionId(tccFbaPlan.getBid(),placementOptionId);

            return R.ok();
        }catch (ApiException e){
            logger.error("请求api设置放置选项失败原因如下:" + e.getResponseBody(),e.getResponseBody(),e);
            return R.error(e.getResponseBody());
        }catch (Exception e){
            logger.error("请求api设置放置选项失败原因如下:" + e.getMessage(),e.getMessage(),e);
            return R.error(e.getMessage());
        }
    }


    /**
     * 获取箱标
     * @param tccFbaDeliver
     * @return
     */
    @Override
    public R getLabels(TccFbaDeliver tccFbaDeliver, TccFbaDeliverItem tccFbaDeliverItem) {
        try {
            TccFbaBoxUp tccFbaBoxUp = new TccFbaBoxUp().setBid(tccFbaDeliverItem.getFbaBoxUpBid()).queryFirst();

            TccFbaBoxUpInfo tccFbaBoxUpInfo = new TccFbaBoxUpInfo().setId(tccFbaDeliverItem.getFbaBoxUpInfoId()).queryFirst();

            TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(tccFbaDeliver.getFbaPlanBid()).queryFirst();

            //获取店铺信息
            JSONObject tpAmazonShop = getTpAmazonShop(tccFbaPlan.getShopId());
            if (tpAmazonShop == null){
                return R.error("网店信息不存在!");
            }
            FbaInboundApiV0 fbaInboundApiV0 = getFbaInboundApiV0(tpAmazonShop);
            if (fbaInboundApiV0 == null){
                return R.error("亚马逊token不存在!");
            }

            //查询物流方式
            TccFbaLogisticsMethod tccFbaLogisticsMethod = new TccFbaLogisticsMethod().setSourceBid(tccFbaDeliver.getBid())
                    .setSourceType(TccFbaLogisticsMethodEnum.SourceType.FBAFH.value)
                    .queryFirst();
            List<TccFbaDeliverSon> tccFbaDeliverSonList = new TccFbaDeliverSon().setFbaDeliverItemId(tccFbaDeliverItem.getId()).queryList();

            List<TccFbaBox> tccFbaBoxList = new TccFbaBox().setBidBoxUp(tccFbaBoxUp.getBid()).queryList();

            StringBuffer weight = new StringBuffer();
            StringBuffer boxNo = new StringBuffer();

            for (TccFbaDeliverSon tccFbaDeliverSon :tccFbaDeliverSonList) {
                List<TccFbaBox>  tccFbaBoxListNew = tccFbaBoxList.stream().filter(item->item.getId().equals(tccFbaDeliverSon.getFbaBoxId())).collect(Collectors.toList());
                TccFbaBox tccFbaBox = tccFbaBoxListNew.get(0);
                weight.append(tccFbaBox.getBoxWeight().stripTrailingZeros().toPlainString());
                weight.append(" + ");

                boxNo.append(tccFbaBox.getBoxNo());
                boxNo.append(" , ");
            }

            String weight1 = weight.substring(0, weight.length() - 3);

            String boxNo1 = boxNo.substring(0, boxNo.length() - 3);

            List<String> packageLabelsToPrint = Arrays.asList("1");
            GetLabelsResponse getLabelsResponse = fbaInboundApiV0.getLabels(tccFbaBoxUpInfo.getFbaNo(),
                    "PackageLabel_Plain_Paper",
                    "BARCODE_2D",
                    null,
                    packageLabelsToPrint,
                    null,
                    tccFbaDeliver.getBoxNum(), 0);
            logger.info("getLabels成功!:" + JSONArray.toJSONString(getLabelsResponse));
            TccFbaInboundApiLog tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("getLabels",tccFbaDeliver.getId().toString(),tccFbaDeliver.getBid(),
                    tccFbaBoxUpInfo.getFbaNo(), JSONArray.toJSONString(getLabelsResponse), 1);
            tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);

            JSONObject jsonObject = new JSONObject();

            //创建其他空白信息页
            String url = pdfService.getLabelsPDF(tccFbaBoxUpInfo.getFbaNo(), tccFbaPlan.getVgsbm() + "/" + tccFbaPlan.getVgsJc(), tccFbaLogisticsMethod.getLogsticsWay(), weight1,boxNo1);
            try {
                URL downloadURL = new URL(getLabelsResponse.getPayload().getDownloadURL());
                HttpURLConnection conn = (HttpURLConnection) downloadURL.openConnection();
                // 设置超时间为3秒
                conn.setConnectTimeout(3 * 1000);
                // 防止屏蔽程序抓取而返回403错误
                conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

                // 得到输入流
                InputStream inputStream = conn.getInputStream();

                byte[] buffer = new byte[1024];
                int len = 0;
                ByteArrayOutputStream bos = new ByteArrayOutputStream();
                while ((len = inputStream.read(buffer)) != -1) {
                    bos.write(buffer, 0, len);
                }
                bos.close();
                // 获取字节数组
                byte[] getData = bos.toByteArray();
                String dir = MyConfig.getProfile();
                // 文件保存位置
                File saveDir = new File(dir);
                if (!saveDir.exists()) {
                    saveDir.mkdir();
                }
                String pdfFileName = "/pdf/" + tccFbaBoxUpInfo.getFbaNo() + "-XB" +  ".pdf";
                File file = new File(saveDir + pdfFileName);
                String data = MyConfig.getUrlDomain() + "/upload/pdf/" + tccFbaBoxUpInfo.getFbaNo() + "-XB" + ".pdf";
                jsonObject.put("downloadURL",data);
                FileOutputStream fos = new FileOutputStream(file);
                fos.write(getData);
                if (fos != null) {
                    fos.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (Exception e) {
                logger.error("下载箱标失败:" + e.getMessage());
                return R.error(e.getMessage());
            }
//            jsonObject.put("downloadURL",getLabelsResponse.getPayload().getDownloadURL());
            jsonObject.put("labelsPDF",url);

            return R.ok(jsonObject);
        } catch (com.bo.sellingpartnerapi.Authorization.invoker.ApiException e) {
            logger.error("获取箱标失败原因如下:" + e.getResponseBody());
            return R.error(e.getResponseBody());
        }catch (Exception e) {
            logger.error("获取箱标失败原因如下:" + e.getMessage());
            return R.error(e.getMessage());
        }
    }


    /**
     * 获取运输选项与交付窗口
     * @param tccFbaBoxUp
     * @return
     */
    @Override
    public R generateTransportationAndDeliveryWindow(TccFbaBoxUp tccFbaBoxUp,String placementOptionId) {
        TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(tccFbaBoxUp.getBidFbaPlan()).queryFirst();
        TccFbaLogisticsMethod tccFbaLogisticsMethod = new TccFbaLogisticsMethod()
                .where("A.SourceBid = '"+tccFbaPlan.getBid()+"'")
                .queryFirst();
        String transportationEn = tccFbaLogisticsMethod.getTransportationEn();

        //自动 - 按SUK发货 自动选择FREIGHT_LTL 发货
        if (tccFbaPlan.getCreationMethod() == 1 && tccFbaPlan.getDeliverState() == 1){
            transportationEn = "FREIGHT_LTL";
        }

        //获取店铺信息
        JSONObject tpAmazonShop = getTpAmazonShop(tccFbaPlan.getShopId());
        if (tpAmazonShop == null){
            return R.error("网店信息不存在!");
        }
        FbaInboundApi fbaInboundApi = getFbaInboundApi(tpAmazonShop);
        if (fbaInboundApi == null){
            return R.error("亚马逊token不存在!");
        }

        try {
            GenerateTransportationOptionsRequest body = new GenerateTransportationOptionsRequest();
            List<ShipmentTransportationConfiguration> shipmentTransportationConfigurationList = new ArrayList<>();
//            //查询这个计划单所有的箱子对应的fba信息
            List<TccFbaBoxUpInfo> tccFbaBoxUpInfoList = new TccFbaBoxUpInfo().setBidFbaPlan(tccFbaBoxUp.getBidFbaPlan()).queryList();
            //String placementOptionId = tccFbaBoxUp.getPlacementOptionId();
            //发货日期 TODO 是否根据当前时间来赋值
            WindowInput windowInput = new WindowInput();
            windowInput.setStart(OffsetDateTime.parse(DateUtils.convertDateToTDate(new Date())));

            for (TccFbaBoxUpInfo tccFbaBoxUpInfo : tccFbaBoxUpInfoList) {
                ShipmentTransportationConfiguration shipmentTransportationConfiguration = new ShipmentTransportationConfiguration();
                shipmentTransportationConfiguration.setShipmentId(tccFbaBoxUpInfo.getFbaId());
                shipmentTransportationConfiguration.setReadyToShipWindow(windowInput);
                shipmentTransportationConfigurationList.add(shipmentTransportationConfiguration);

                //每一个fba号生成交付窗口
                GenerateDeliveryWindowOptionsResponse generateDeliveryWindowOptionsResponse = fbaInboundApi.generateDeliveryWindowOptions(
                        tccFbaPlan.getInboundPlanId(),
                        tccFbaBoxUpInfo.getFbaId());
                logger.info("generateDeliveryWindowOptions传参!:" + tccFbaPlan.getInboundPlanId()+"；"+tccFbaBoxUpInfo.getFbaId());
                logger.info("generateDeliveryWindowOptions成功返回!:" + JSONArray.toJSONString(generateDeliveryWindowOptionsResponse));
                TccFbaInboundApiLog tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("generateDeliveryWindowOptions", tccFbaBoxUpInfo.getFbaId(), tccFbaPlan.getBid(),
                        tccFbaBoxUpInfo.getFbaId(), JSONArray.toJSONString(generateDeliveryWindowOptionsResponse), 1);
                tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);

                R r = getInboundOperationStatusListWait15(generateDeliveryWindowOptionsResponse.getOperationId(),fbaInboundApi);
                if (r.getCode() != 0){
                    tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("getInboundOperationStatusDeliveryWindowOptions",tccFbaBoxUpInfo.getFbaId(),tccFbaPlan.getBid(),
                            generateDeliveryWindowOptionsResponse.getOperationId(), r.getMsg(), 1);
                    tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                    logger.error("generateDeliveryWindowOptions获取交付窗口失败原因如下:" +  r.getMsg());
                    return R.error("获取交付窗口失败,失败原因如下:" + r.getMsg());
                }
            }

            body.setPlacementOptionId(placementOptionId);
            body.setShipmentTransportationConfigurations(shipmentTransportationConfigurationList);

            logger.info("generateTransportationOptions传参!:" +  tccFbaPlan.getInboundPlanId()+"；"+body);
            //批量生成fba的运输选项
            GenerateTransportationOptionsResponse generateTransportationOptionsResponse = fbaInboundApi.generateTransportationOptions(
                    tccFbaPlan.getInboundPlanId(), body);
            logger.info("generateTransportationOptions成功返回!:" + JSONArray.toJSONString(generateTransportationOptionsResponse));
            TccFbaInboundApiLog tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("generateTransportationOptions", tccFbaPlan.getId().toString(), tccFbaPlan.getBid(),
                    JSONArray.toJSONString(body), JSONArray.toJSONString(generateTransportationOptionsResponse), 1);
            tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);

            R r = getInboundOperationStatusListWait15(generateTransportationOptionsResponse.getOperationId(),fbaInboundApi);
            if (r.getCode() != 0){
                tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("generateTransportationOptionsResponse-Res",tccFbaPlan.getId().toString(),tccFbaPlan.getBid(),
                        generateTransportationOptionsResponse.getOperationId(), r.getMsg(), 1);
                tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                logger.error("批量生成fba的运输选项失败原因如下:" +  r.getMsg());
                return R.error("批量生成fba的运输选项失败,失败原因如下:" + r.getMsg());
            }

            for (TccFbaBoxUpInfo tccFbaBoxUpInfo : tccFbaBoxUpInfoList) {
                //获取承运人
                Boolean bool = true;
                ListTransportationOptionsResponse listTransportationOptionsResponse = null;
                String paginationToken = null;
                String transportationOptionId = null;
                while (bool) {
                    listTransportationOptionsResponse = fbaInboundApi.listTransportationOptions(
                            tccFbaPlan.getInboundPlanId(),
                            20,paginationToken , placementOptionId,
                            tccFbaBoxUpInfo.getFbaId());
                    logger.info("listTransportationOptions传参!:" +   tccFbaPlan.getInboundPlanId()+"；"+20+"；"+paginationToken+"；"+placementOptionId+"；"+ tccFbaBoxUpInfo.getFbaId());
                    logger.info("listTransportationOptions成功返回!:" + JSONArray.toJSONString(listTransportationOptionsResponse));
                    tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("listTransportationOptions", tccFbaBoxUpInfo.getFbaId(), tccFbaPlan.getBid(),
                            tccFbaPlan.getInboundPlanId(), JSONArray.toJSONString(listTransportationOptionsResponse), 1);
                    tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                    //这里将所有的选项都查询出来
                    for (TransportationOption transportationOption : listTransportationOptionsResponse.getTransportationOptions()){
                        if (transportationOption.getCarrier() != null){
//                            if(transportationOption.getCarrier().getName().equals("Other")){
//                                logger.info("TransportationOptionId *********** Other对应:" + transportationOption.getShippingMode());
//                            }
//                            if(transportationOption.getShippingMode().equals(transportationEn)){
//                                logger.info("TransportationOptionId *********** " + transportationEn+"对应:" + transportationOption.getCarrier().getName());
//                            }
                            //shippingMode GROUND_SMALL_PARCEL  carrier = Other (选择对应物流方式里面的运输方式,类型carrier 选择other)
                            if(transportationOption.getCarrier().getName().equals("Other") && transportationOption.getShippingMode().equals("GROUND_SMALL_PARCEL")){
                                // 此id就是用于后续设置
                                transportationOptionId = transportationOption.getTransportationOptionId();
                                //判断是哪个fba号的 设置fba数据
                                if(transportationOptionId!=null){
                                    tccFbaBoxUpInfo.setTransportationOptionId(transportationOption.getTransportationOptionId());
                                    tccFbaBoxUpInfoMapper.update(tccFbaBoxUpInfo);
                                    bool = false;
                                }
                            }
                        }
                    }
                    if (listTransportationOptionsResponse.getPagination().getNextToken() == null) {
                        bool = false;
                    }else {
                        paginationToken = listTransportationOptionsResponse.getPagination().getNextToken();
                    }
                }
            }



            OffsetDateTime now = OffsetDateTime.now();
            // 在当前时间上加30天
            OffsetDateTime futureDate = now.plus(tccFbaLogisticsMethod.getEstimatedDayFrom(), ChronoUnit.DAYS);
            OffsetDateTime futureDates = now.plus(tccFbaLogisticsMethod.getEstimatedDayTo(), ChronoUnit.DAYS);

            for (TccFbaBoxUpInfo tccFbaBoxUpInfo : tccFbaBoxUpInfoList) {
                //获取交付窗口信息
                // 这里是否需要再TccFbaBoxUpInfo再加一个deliveryWindowOptionId 字段
                ListDeliveryWindowOptionsResponse listDeliveryWindowOptionsResponse = fbaInboundApi.listDeliveryWindowOptions(
                        tccFbaPlan.getInboundPlanId(), tccFbaBoxUpInfo.getFbaId(), null, null);
                logger.info("listDeliveryWindowOptions成功!:" + JSONArray.toJSONString(listDeliveryWindowOptionsResponse));
                tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("listDeliveryWindowOptions", tccFbaBoxUpInfo.getFbaId(), tccFbaPlan.getBid(),
                        JSONArray.toJSONString(tccFbaPlan.getInboundPlanId()), JSONArray.toJSONString(listDeliveryWindowOptionsResponse), 1);
                tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);

                //没有取到对应的值提示报错
                for (DeliveryWindowOption deliveryWindowOption : listDeliveryWindowOptionsResponse.getDeliveryWindowOptions()){
                    boolean isAfter = deliveryWindowOption.getStartDate().isBefore(futureDate);
                    boolean isBefore = deliveryWindowOption.getEndDate().isAfter(futureDates);
                    if (isBefore && isAfter){
                        tccFbaBoxUpInfo.setDeliveryWindowOptionId(deliveryWindowOption.getDeliveryWindowOptionId());
                        //tccFbaBoxUpInfo.setTransportationOptionId(transportationOptionId);
                        tccFbaBoxUpInfoMapper.update(tccFbaBoxUpInfo);
                    }
                }
            }
        } catch (ApiException e) {
            logger.error("获取运输与交付窗口选项失败原因如下:" + e.getResponseBody(),e.getResponseBody(),e);
            return R.error(e.getResponseBody());
        }catch (Exception e) {
            logger.error("获取运输与交付窗口选项失败原因如下:" + e.getMessage(),e.getMessage(),e);
            return R.error(e.getMessage());
        }
        return R.ok();
    }



    /**
     * 设置运输选项与交付窗口
     * @param tccFbaBoxUp
     * @return
     */
    @Override
    public R confirmTransportationAndDeliveryWindow(TccFbaBoxUp tccFbaBoxUp,String placementOptionId) {
        TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(tccFbaBoxUp.getBidFbaPlan()).queryFirst();
        //获取店铺信息
        JSONObject tpAmazonShop = getTpAmazonShop(tccFbaPlan.getShopId());
        if (tpAmazonShop == null){
            return R.error("网店信息不存在!");
        }
        FbaInboundApi fbaInboundApi = getFbaInboundApi(tpAmazonShop);
        if (fbaInboundApi == null){
            return R.error("亚马逊token不存在!");
        }
        try {
            ConfirmTransportationOptionsRequest body = new ConfirmTransportationOptionsRequest();
            List<TransportationSelection> transportationSelections = new ArrayList();
            //查询这个计划单所有的箱子对应的fba信息
            List<TccFbaBoxUpInfo> tccFbaBoxUpInfoList = new TccFbaBoxUpInfo().setBidFbaPlan(tccFbaPlan.getBid()).queryList();
            for (TccFbaBoxUpInfo tccFbaBoxUpInfo : tccFbaBoxUpInfoList) {
                //设置交付窗口信息
                ConfirmDeliveryWindowOptionsResponse confirmDeliveryWindowOptionsResponse = fbaInboundApi.confirmDeliveryWindowOptions(
                        tccFbaPlan.getInboundPlanId(),
                        tccFbaBoxUpInfo.getFbaId(),
                        tccFbaBoxUpInfo.getDeliveryWindowOptionId());
                logger.info("confirmDeliveryWindowOptions成功!:" + JSONArray.toJSONString(confirmDeliveryWindowOptionsResponse));
                TccFbaInboundApiLog tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("confirmDeliveryWindowOptions", tccFbaBoxUpInfo.getFbaId(), tccFbaPlan.getBid(),
                        tccFbaBoxUpInfo.getDeliveryWindowOptionId(), JSONArray.toJSONString(confirmDeliveryWindowOptionsResponse), 1);
                tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);

                TransportationSelection transportationSelection = new TransportationSelection();
                transportationSelection.setShipmentId(tccFbaBoxUpInfo.getFbaId());
                transportationSelection.setTransportationOptionId(tccFbaBoxUpInfo.getTransportationOptionId());
                transportationSelections.add(transportationSelection);
            }
            body.setTransportationSelections(transportationSelections);

            ConfirmTransportationOptionsResponse confirmTransportationOptionsResponse = fbaInboundApi.confirmTransportationOptions(
                    tccFbaPlan.getInboundPlanId(),
                    body);
            logger.info("confirmTransportationOptions成功!:" + JSONArray.toJSONString(confirmTransportationOptionsResponse));
            TccFbaInboundApiLog tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("confirmTransportationOptions", tccFbaPlan.getId().toString(), tccFbaPlan.getBid(),
                    JSONArray.toJSONString(body), JSONArray.toJSONString(confirmTransportationOptionsResponse), 1);
            tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
            
        } catch (ApiException e) {
            logger.error("设置运输选项与交付窗口失败原因如下:" + e.getResponseBody(),e.getResponseBody(),e);
            return R.error(e.getResponseBody());
        }catch (Exception e) {
            logger.error("设置运输选项与交付窗口失败原因如下:" + e.getMessage(),e.getMessage(),e);
            return R.error(e.getMessage());
        }
        return R.ok();
    }



    /**
     * 设置交付窗口
     * @param tccFbaBoxUp
     * @return
     */
    @Override
    public R confirmDeliveryWindow(TccFbaBoxUp tccFbaBoxUp,String placementOptionId) {
        TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(tccFbaBoxUp.getBidFbaPlan()).queryFirst();
        //获取店铺信息
        JSONObject tpAmazonShop = getTpAmazonShop(tccFbaPlan.getShopId());
        if (tpAmazonShop == null){
            return R.error("网店信息不存在!");
        }
        FbaInboundApi fbaInboundApi = getFbaInboundApi(tpAmazonShop);
        if (fbaInboundApi == null){
            return R.error("亚马逊token不存在!");
        }
        try {
            //查询这个计划单所有的箱子对应的fba信息
            List<TccFbaBoxUpInfo> tccFbaBoxUpInfoList = new TccFbaBoxUpInfo().setBidFbaPlan(tccFbaPlan.getBid()).queryList();
            List<ConfirmDeliveryWindowOptionsResponse> responseList = new ArrayList<>();
            for (TccFbaBoxUpInfo tccFbaBoxUpInfo : tccFbaBoxUpInfoList) {
                //设置交付窗口信息
                ConfirmDeliveryWindowOptionsResponse confirmDeliveryWindowOptionsResponse = fbaInboundApi.confirmDeliveryWindowOptions(
                        tccFbaPlan.getInboundPlanId(),
                        tccFbaBoxUpInfo.getFbaId(),
                        tccFbaBoxUpInfo.getDeliveryWindowOptionId());
                logger.info("confirmDeliveryWindowOptions传参!:" +   tccFbaPlan.getInboundPlanId()+"；"+ tccFbaBoxUpInfo.getFbaId()+"；"+tccFbaBoxUpInfo.getDeliveryWindowOptionId());
                logger.info("confirmDeliveryWindowOptions成功返回!:" + JSONArray.toJSONString(confirmDeliveryWindowOptionsResponse));
                TccFbaInboundApiLog tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("confirmDeliveryWindowOptions", tccFbaBoxUpInfo.getFbaId(), tccFbaPlan.getBid(),
                        tccFbaBoxUpInfo.getDeliveryWindowOptionId(), JSONArray.toJSONString(confirmDeliveryWindowOptionsResponse), 1);
                tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                responseList.add(confirmDeliveryWindowOptionsResponse);

            }

            if(responseList.size()>0){
                for(int i=0;i<responseList.size();i++){
                    ConfirmDeliveryWindowOptionsResponse confirmDeliveryWindowOptionsResponse = responseList.get(i);
                    R r = getInboundOperationStatusListWait15(confirmDeliveryWindowOptionsResponse.getOperationId(),fbaInboundApi);
                    if (r.getCode() != 0){
                        TccFbaInboundApiLog tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("confirmDeliveryWindowOptions-Res",tccFbaPlan.getId().toString(),tccFbaPlan.getBid(),
                                confirmDeliveryWindowOptionsResponse.getOperationId(), r.getMsg(), 1);
                        tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                        logger.error("设置交付窗口失败原因如下:" +  r.getMsg());
                        return R.error("设置交付窗口失败,失败原因如下:" + r.getMsg());
                    }
                }
            }

        } catch (ApiException e) {
            logger.error("设置交付窗口失败原因如下:" + e.getResponseBody(),e.getResponseBody(),e);
            return R.error(e.getResponseBody());
        } catch (Exception e) {
            logger.error("设置交付窗口失败原因如下:" + e.getMessage(),e.getMessage(),e);
            return R.error(e.getMessage());
        }
        return R.ok();
    }


    /**
     * 设置运输选项
     * @param tccFbaBoxUp
     * @return
     */
    @Override
    public R confirmTransportation(TccFbaBoxUp tccFbaBoxUp,String placementOptionId) {
        TccFbaPlan tccFbaPlan = new TccFbaPlan().setBid(tccFbaBoxUp.getBidFbaPlan()).queryFirst();
        //获取店铺信息
        JSONObject tpAmazonShop = getTpAmazonShop(tccFbaPlan.getShopId());
        if (tpAmazonShop == null){
            return R.error("网店信息不存在!");
        }
        FbaInboundApi fbaInboundApi = getFbaInboundApi(tpAmazonShop);
        if (fbaInboundApi == null){
            return R.error("亚马逊token不存在!");
        }

        try {
            ConfirmTransportationOptionsRequest body = new ConfirmTransportationOptionsRequest();
            List<TransportationSelection> transportationSelections = new ArrayList();
            //查询这个计划单所有的箱子对应的fba信息
            List<TccFbaBoxUpInfo> tccFbaBoxUpInfoList = new TccFbaBoxUpInfo().setBidFbaPlan(tccFbaPlan.getBid()).queryList();
            for (TccFbaBoxUpInfo tccFbaBoxUpInfo : tccFbaBoxUpInfoList) {
                TransportationSelection transportationSelection = new TransportationSelection();
                transportationSelection.setShipmentId(tccFbaBoxUpInfo.getFbaId());
                transportationSelection.setTransportationOptionId(tccFbaBoxUpInfo.getTransportationOptionId());
                transportationSelections.add(transportationSelection);
            }
            body.setTransportationSelections(transportationSelections);

            ConfirmTransportationOptionsResponse confirmTransportationOptionsResponse = fbaInboundApi.confirmTransportationOptions(
                    tccFbaPlan.getInboundPlanId(),
                    body);
            logger.info("confirmTransportationOptions传参!:" +   tccFbaPlan.getInboundPlanId()+"；"+ body);
            logger.info("confirmTransportationOptions成功返回!:" + JSONArray.toJSONString(confirmTransportationOptionsResponse));
            TccFbaInboundApiLog tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("confirmTransportationOptions", tccFbaPlan.getId().toString(), tccFbaPlan.getBid(),
                    JSONArray.toJSONString(body), JSONArray.toJSONString(confirmTransportationOptionsResponse), 1);
            tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);

            R r = getInboundOperationStatusListWait15(confirmTransportationOptionsResponse.getOperationId(),fbaInboundApi);
            if (r.getCode() != 0){
                tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("confirmTransportationOptions-Res",tccFbaPlan.getId().toString(),tccFbaPlan.getBid(),
                        confirmTransportationOptionsResponse.getOperationId(), r.getMsg(), 1);
                tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                logger.error("设置运输选项失败原因如下:" +  r.getMsg());
                return R.error("设置运输选项失败,失败原因如下:" + r.getMsg());
            }


        } catch (ApiException e) {
            logger.error("设置运输选项失败原因如下:" + e.getResponseBody(),e.getResponseBody(),e);
            return R.error(e.getResponseBody());
        }catch (Exception e) {
            logger.error("设置运输选项失败原因如下:" + e.getMessage(),e.getMessage(),e);
            return R.error(e.getMessage());
        }
        return R.ok();
    }




    /**
     *  获取店铺信息
     * @param id 店铺id
     * @return
     */
    private JSONObject getTpAmazonShop(Long id){
        Map<String, Object> tpAmazonShop = new TpAmazonShop()
                .addLeftJoin("TP_AmazonSeller tsell on tsell.id = A.amazonSellerId")//卖家管理
                .addField("tsell.refreshToken as refreshToken,tsell.regionCode as regionCode,tsell.regionName")
                .addLeftJoin("TB_Site ts on ts.id = A.SiteId")//站点
                .addField("ts.AmazonMarketplaceId AS marketplaceId")
                .addLeftJoin("TB_Country tc on tc.id = ts.CountryId")//国家
                .addField("tc.name AS countryName,tc.code AS countryCode")
                .addLeftJoin("TP_AmazonRegion tar on tar.Code = ts.regionCode")//平台地区
                .addField("tar.AwsRegion awsRegion,tar.AmazonServiceUrl amazonServiceUrl,tar.code amazonRegionCode")
                .where(" A.id =" + id)
                .queryFirstMap();
        JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(tpAmazonShop));
        return jsonObject;
    }


    /**
     *  获取FbaInboundApi的参数
     * @param jsonObject 店铺信息
     * @return
     */
    private FbaInboundApi getFbaInboundApi(JSONObject jsonObject){
        //平台
        TbPlatform tbPlatform = new TbPlatform().setCode("PTBM001").queryFirst();
        if (tbPlatform == null) {
            return null;
        }
        String encryptSecret = AESUtil.aesDecrypt(tbPlatform.getEncryptSecret());
        LWAAuthorizationCredentials lwaAuthorizationCredentials = LWAAuthorizationCredentials.builder()
                .clientId(MyConfig.getAmazonLwaClientKey())
                .clientSecret(encryptSecret)
                .refreshToken(jsonObject.get("refreshToken").toString())
                .endpoint(MyConfig.getAmazonLwaEndpoint())
                .build();


        FbaInboundApi api = new FbaInboundApi.Builder()
                .lwaAuthorizationCredentials(lwaAuthorizationCredentials)
                .endpoint(jsonObject.get("amazonServiceUrl").toString())
                .build();
        return api;
    }

    /**
     *  获取FbaInboundApiV0的参数
     * @param jsonObject 店铺信息
     * @return
     */
    private FbaInboundApiV0 getFbaInboundApiV0(JSONObject jsonObject){
        //平台
        TbPlatform tbPlatform = new TbPlatform().setCode("PTBM001").queryFirst();
        if (tbPlatform == null) {
            return null;
        }
        String encryptSecret = AESUtil.aesDecrypt(tbPlatform.getEncryptSecret());
        SellerSecretsVO secretsVO;
        secretsVO = new SellerSecretsVO();
        FbaInboundApiV0 api;
        secretsVO.setAWSAuthenticationCredentials_AK(MyConfig.getAmazonAwsAccessKey());
        secretsVO.setAWSAuthenticationCredentials_SK(MyConfig.getAmazonAwsAccessSecret());
        secretsVO.setAWSAuthenticationCredentialsProvider_roleArn(MyConfig.getAmazonRoleArn());
        secretsVO.setlWAAuthorizationCredentials_clientid(MyConfig.getAmazonLwaClientKey());
        secretsVO.setLWAAuthorizationCredentials_clientSecret(encryptSecret);
        secretsVO.setSeller_id(jsonObject.get("sellerId").toString());
        secretsVO.setLWAAuthorizationCredentials_refreshToken(jsonObject.get("refreshToken").toString());
        secretsVO.setMarketPlace(jsonObject.get("amazonRegionCode").toString());
        api = Helper.buildApi(secretsVO, FbaInboundApiV0.class);
        return api;
    }

    private R getInboundOperationStatusList(String operationId,FbaInboundApi fbaInboundApi){
        try {
            boolean bool = true;
            long millis = 1000L;
            while (bool){
                InboundOperationStatus inboundOperationStatus = fbaInboundApi.getInboundOperationStatus(operationId);
                if (inboundOperationStatus.getOperationStatus().getValue().equals(OperationStatus.FAILED.getValue())){
                    return R.error(inboundOperationStatus.getOperationProblems().get(0).getMessage());
                }
                if (inboundOperationStatus.getOperationStatus().getValue().equals(OperationStatus.SUCCESS.getValue())){
                    return R.ok();
                }
                Thread.sleep(millis);
                millis = millis *2;
                if (millis > 27000L){
                    return R.error("请求亚马逊api等待超时,请联系管理员,或者稍等后再次操作!");
                }
            }
        } catch (ApiException e) {
            return R.error(e.getResponseBody());
        } catch (Exception e) {
            return R.error(e.getMessage());
        }
        return R.ok();
    }



    private R getInboundOperationStatusListNoWait(String operationId,FbaInboundApi fbaInboundApi){
        try {
            boolean bool = true;
            long millis = 1000L;
            while (bool){
                InboundOperationStatus inboundOperationStatus = fbaInboundApi.getInboundOperationStatus(operationId);
                if (inboundOperationStatus.getOperationStatus().getValue().equals(OperationStatus.FAILED.getValue())){
                    return R.error(inboundOperationStatus.getOperationProblems().get(0).getMessage());
                }
                if (inboundOperationStatus.getOperationStatus().getValue().equals(OperationStatus.SUCCESS.getValue())){
                    return R.ok();
                }
                Thread.sleep(millis);
            }
        } catch (ApiException e) {
            return R.error(e.getResponseBody());
        } catch (Exception e) {
            return R.error(e.getMessage());
        }
        return R.ok();
    }



    private R getInboundOperationStatusListWait15(String operationId,FbaInboundApi fbaInboundApi){
        try {
            boolean bool = true;
            long millis = 1000L;
            int count = 0;
            while (bool){
                InboundOperationStatus inboundOperationStatus = fbaInboundApi.getInboundOperationStatus(operationId);
                logger.info("获取接口成功与否返回结果（次数："+count+"）："+inboundOperationStatus);
                if (inboundOperationStatus.getOperationStatus().getValue().equals(OperationStatus.FAILED.getValue())){
                    return R.error(inboundOperationStatus.getOperationProblems().get(0).getMessage());
                }
                if (inboundOperationStatus.getOperationStatus().getValue().equals(OperationStatus.SUCCESS.getValue())){
                    return R.ok();
                }
                Thread.sleep(millis);
                count++;
                if (count > 60){
                    return R.error("请求亚马逊api等待超时,请联系管理员,或者稍等后再次操作!");
                }
            }
        } catch (ApiException e) {
            logger.error("获取接口成功与否出错："+e.getResponseBody(),e);
            return R.error(e.getResponseBody());
        } catch (Exception e) {
            logger.error("获取接口成功与否出错："+e.getMessage(),e);
            return R.error(e.getMessage());
        }
        return R.ok();
    }



    //设置运输选项与交付窗口后，重新获取FBA信息
    @Override
    public R reSearchShipments(String boxUpBid,TccFbaPlan tccFbaPlan,String placementOptionId){
        try{
            //获取店铺信息
            JSONObject tpAmazonShop = getTpAmazonShop(tccFbaPlan.getShopId());
            if (tpAmazonShop == null){
                return R.error("网店信息不存在!");
            }
            FbaInboundApi fbaInboundApi = getFbaInboundApi(tpAmazonShop);
            if (fbaInboundApi == null){
                return R.error("亚马逊token不存在!");
            }
            //获取放置选项
            ListPlacementOptionsResponse listPlacementOptionsResponse = fbaInboundApi.listPlacementOptions(tccFbaPlan.getInboundPlanId(), null, null);

            TccFbaInboundApiLog tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog(
                    "listPlacementOptions-doExamineByAutoAndBox", tccFbaPlan.getId().toString(), tccFbaPlan.getBid(),
                    placementOptionId, JSONArray.toJSONString(listPlacementOptionsResponse), 1);
            tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);

            logger.info("listPlacementOptions成功!:" + JSONArray.toJSONString(listPlacementOptionsResponse));
            PlacementOption placementOptionByChoose = null;
            for (PlacementOption placementOption :  listPlacementOptionsResponse.getPlacementOptions()){
                if (placementOption.getPlacementOptionId().equals(placementOptionId)) {
                    placementOptionByChoose = placementOption;
                }
            }

            if(placementOptionByChoose!=null){
                //查询货件详情
                for (String shipmentId : placementOptionByChoose.getShipmentIds()){
                    TccFbaBoxUpInfo addInfo = new TccFbaBoxUpInfo().setFbaId(shipmentId).queryFirst();
                    Shipment shipment = fbaInboundApi.getShipment(tccFbaPlan.getInboundPlanId(), shipmentId);

                    tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog(
                            "getShipment-doExamineByAutoAndBox", shipmentId, tccFbaPlan.getBid(),
                            placementOptionId, JSONArray.toJSONString(shipment), 1);
                    tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);


                    List<Incentive> fees = placementOptionByChoose.getFees();
                    addInfo.setFbaNo(shipment.getShipmentConfirmationId());
                    addInfo.setFbaTrackNo(shipment.getAmazonReferenceId());
                    addInfo.setFbaToken(null);
                    addInfo.setFbaId(shipmentId);
                    addInfo.setFbaWarehouse(shipment.getDestination().getWarehouseId());
                    if (shipment.getDestination().getAddress() != null) {
                        io.swagger.client.model.Address address = shipment.getDestination().getAddress();
                        addInfo.setFbaWarehouseAddr(address.getPostalCode());
                    }
                    BigDecimal fee = BigDecimal.ZERO;
                    if(fees!=null && fees.size()>0){
                        for (int k = 0; k < fees.size(); k++) {
                            Incentive feeJs = fees.get(k);
                            if (feeJs.getTarget().equals("Placement Services")) {
                                if(feeJs.getValue()!=null){
                                    Currency currency = feeJs.getValue();
                                    //JSONObject feeValue = JSON.parseObject(feeJs.getValue().toString());
                                    if (currency!=null && currency.getCurrencyAmount()!=null) {
                                        fee = currency.getCurrencyAmount();
                                    }
                                }

                            }
                        }
                    }

                    addInfo.setFbaAmount(fee.compareTo(BigDecimal.ZERO) == 0 ? null : fee);

                    tccFbaBoxUpInfoMapper.update(addInfo);
                }
            }
            return R.ok();

        }catch (ApiException e){
            logger.error("reSearchShipments - api失败原因如下:" + e.getResponseBody(), e.getResponseBody(),e);
            return R.error(e.getResponseBody());
        }catch (Exception e){
            logger.error("reSearchShipments - api失败原因如下:" + e.getMessage(), e.getMessage(),e);
            return R.error(e.getMessage());
        }
    }


    //按箱自动，匹配箱子信息
    @Override
    public R getListShipmentBoxesResponse(TccFbaPlan tccFbaPlan){

        try{

        //获取店铺信息
            JSONObject tpAmazonShop = getTpAmazonShop(tccFbaPlan.getShopId());
            if (tpAmazonShop == null){
                return R.error("网店信息不存在!");
            }
            FbaInboundApi fbaInboundApi = getFbaInboundApi(tpAmazonShop);
            if (fbaInboundApi == null){
                return R.error("亚马逊token不存在!");
            }

            //List<TccFbaBoxDetail> detailList = new TccFbaBoxDetail().setBidFbaPlan(tccFbaPlan.getBid()).queryList();
            List<Map<String,Object>> detailList = new TccFbaBoxDetail()
                    //.setBidBoxUp(tccFbaBoxUp.getBid())
                    .addLeftJoin("TCC_FbaBoxUp B ON B.Bid = A.BidBoxUp")
                    .where("B.BidFbaPlan = '"+tccFbaPlan.getBid()+"'")
                    .addLeftJoin("TCC_FbaBoxUpItem C ON C.Id = A.BoxUpItemId")
                    .addField("C.AverageBoxUpNum AS averageBoxUpNum")
                    .addLeftJoin("TCC_FbaPlanItem D ON C.FbaPlanItemId = D.Id")
                    .addField("D.Sku AS sku")
                    .addField("D.FnSku AS fnSku")
                    .addField("D.Asin AS asin")

                    .queryMap();

            List<TccFbaBox> tccFbaBoxList = new TccFbaBox().setBidFbaPlan(tccFbaPlan.getBid()).queryList();
            //List<TccFbaBoxUpItem> boxUpItemList = new TccFbaBoxUpItem().setBidFbaPlan(tccFbaPlan.getBid()).queryList();
            //List<TccFbaPlanItem> planItemList = new TccFbaPlanItem().setBidFbaPlan(tccFbaPlan.getBid()).queryList();

            //存放已经添加过的数据
            List<TccFbaBox> boxListIsSeted = new ArrayList<>();

            List<TccFbaBoxUpInfo> infoList = new TccFbaBoxUpInfo().setBidFbaPlan(tccFbaPlan.getBid()).queryList();

            for(TccFbaBoxUpInfo tccFbaBoxUpInfo:infoList){
                //获取装箱信息
                ListShipmentBoxesResponse listShipmentBoxesResponse = fbaInboundApi.listShipmentBoxes(
                        tccFbaPlan.getInboundPlanId(),tccFbaBoxUpInfo.getFbaId(), null, null);
                TccFbaInboundApiLog tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("listShipmentBoxesResponse",tccFbaBoxUpInfo.getFbaId(),tccFbaPlan.getBid(),
                        tccFbaBoxUpInfo.getFbaId(), JSONArray.toJSONString(listShipmentBoxesResponse), 1);
                tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                logger.info("listShipmentBoxesResponse成功!:" + JSONArray.toJSONString(listShipmentBoxesResponse));

                List<Box> boxes = listShipmentBoxesResponse.getBoxes();
                if(boxes!=null && boxes.size()>0){
                    Long detailId = null;
                    for(Box box:boxes){

                        boolean isAddByBox = false;
                        Dimensions dimensions = box.getDimensions();
                        logger.info("箱规dimensions:" + dimensions);
                        List<Item> items = box.getItems();
                        List<TccFbaBox> tccFbaBoxListBySize = null;
                        //****** 1、匹配长、宽、高 ******
                        if (!tpAmazonShop.get("amazonRegionCode").toString().equals("EUROPE")){//欧洲 || 其他国家
                            tccFbaBoxListBySize = tccFbaBoxList.stream()
                                    .filter(e->
                                            e.getBoxLong().multiply(new BigDecimal(0.3937008)).setScale(2, BigDecimal.ROUND_HALF_UP).compareTo(dimensions.getLength())==0 // 长
                                                    && e.getBoxWide().multiply(new BigDecimal(0.3937008)).setScale(2, BigDecimal.ROUND_HALF_UP).compareTo(dimensions.getWidth())==0 //宽
                                                    && e.getBoxHigh().multiply(new BigDecimal(0.3937008)).setScale(2, BigDecimal.ROUND_HALF_UP).compareTo(dimensions.getHeight())==0 //高
                                    ).collect(Collectors.toList());

                        }else {
                            tccFbaBoxListBySize = tccFbaBoxList.stream()
                                    .filter(e->
                                            e.getBoxLong().compareTo(dimensions.getLength())==0 // 长
                                                    && e.getBoxWide().compareTo(dimensions.getWidth())==0 //宽
                                                    && e.getBoxHigh().compareTo(dimensions.getHeight())==0 //高
                                    ).collect(Collectors.toList());
                        }

                        if(tccFbaBoxListBySize.size()>0){
                            //编辑关联信息
                            int sameNum = 0;
                            for(TccFbaBox tccFbaBox:tccFbaBoxListBySize){

                            logger.info("tccFbaBox:" + tccFbaBox.getId());
                                boolean boxIsAllSame = true;
                                StringBuffer isSame = new StringBuffer();
                                //****** 2、匹配箱子内的商品信息 商品件数 、 商品SKU、数量 ******
                                int creationMethod = tccFbaPlan.getCreationMethod();//下单方式(0.手动|1.自动)
                                if(creationMethod == 1 && tccFbaPlan.getEvenlyBoxNum()!=null && tccFbaPlan.getEvenlyBoxNum()>=5){
                                    //均分不匹配箱子内商品数据
                                }else {
                                    //List<TccFbaBoxDetail> detailListByBoxId = detailList.stream().filter(e->e.getBoxId().equals(tccFbaBox.getId())).collect(Collectors.toList());
                                    List<Map<String,Object>> detailListByBoxId = detailList.stream().filter(e->Integer.parseInt(e.get("boxId").toString())==tccFbaBox.getId()).collect(Collectors.toList());

                                    if(detailListByBoxId.size()>0){
                                        //根据sku 去重
                                        Map<String, List<Map<String, Object>>> groupsByStr = detailListByBoxId.stream().collect(Collectors.groupingBy(e->e.get("sku").toString()));
                                        int skuNum = groupsByStr.size();
                                        //匹配 箱子内商品 数据数量是否对应
                                        if(skuNum != items.size()){
                                            logger.info("箱子内商品 数据数量不对应：skuNum:" + skuNum+";items.size():"+items.size());
                                            continue;
                                        }

                                        if(creationMethod == 1 && tccFbaPlan.getEvenlyBoxNum()!=null && tccFbaPlan.getEvenlyBoxNum()>=5){
                                            //均分不匹配箱子内商品数据
                                        }else{
                                            //遍历，分组的信息
                                            groupsByStr.forEach((sku, groupListBySku) -> {

                                                int num = 0;
                                                for(Map<String,Object> info:groupListBySku){
                                                    num = num + Integer.parseInt(info.get("num").toString());
//                                            //数量出现均分装箱存在≥5，按照商品均分装箱数量上传
//                                            if(creationMethod == 1 && tccFbaPlan.getEvenlyBoxNum()!=null && tccFbaPlan.getEvenlyBoxNum()>=5){
//                                                num = num + Integer.parseInt(info.get("averageBoxUpNum").toString());
//                                            }else {
//                                                num = num + Integer.parseInt(info.get("num").toString());
//                                            }
                                                }
                                                Map<String, Object> item = groupListBySku.get(0);
                                                //匹配商品SKU、数量
                                                int sameCount = 0;
                                                for(Item itemInfo : items){
                                                    logger.error("*****匹配:"+itemInfo.getAsin()+" =====> "+item.get("asin").toString());
                                                    logger.error("*****匹配:"+itemInfo.getFnsku()+" =====> "+item.get("fnSku").toString());
                                                    logger.error("*****匹配:"+itemInfo.getQuantity()+" =====> "+num);
                                                    if(itemInfo.getAsin().equals(item.get("asin").toString())
                                                            && itemInfo.getFnsku().equals(item.get("fnSku").toString())
                                                            && itemInfo.getQuantity() == num){
                                                        sameCount ++;
                                                    }

                                                }
                                                if(sameCount <=0 ) {
                                                    //boxIsAllSame = false;
                                                    isSame.append("1");
                                                }
                                            });
                                            if(isSame.length()>0){
                                                boxIsAllSame = false;
                                            }
                                        }

//                                    for(TccFbaBoxDetail boxDetail:detailListByBoxId){
//                                        TccFbaBoxUpItem boxUpItem = boxUpItemList.stream()
//                                                .filter(e->e.getId().equals(boxDetail.getBoxUpItemId()))
//                                                .collect(Collectors.toList()).get(0);
//                                        //计划单单子列表
//                                        TccFbaPlanItem planItem = planItemList.stream()
//                                                .filter(e->e.getId().equals(boxUpItem.getFbaPlanItemId()))
//                                                .collect(Collectors.toList()).get(0);
//                                        //匹配商品SKU、数量
//                                        long itemsBySku = items.stream().filter(e->{
//                                            logger.error("*****匹配:"+e.getAsin()+" =====> "+planItem.getAsin());
//                                            logger.error("*****匹配:"+e.getFnsku()+" =====> "+planItem.getFnSku());
//                                            logger.error("*****匹配:"+e.getQuantity()+" =====> "+boxDetail.getNum());
//                                            return e.getAsin().equals(planItem.getAsin()) &&e.getFnsku().equals(planItem.getFnSku()) &&  e.getQuantity().equals(boxDetail.getNum());
//                                        }).count();
//                                        if(itemsBySku <=0 ) {
//                                            boxIsAllSame = false;
//                                        }
//                                    }
                                    }else {
                                        boxIsAllSame = false;
                                    }
                                }

                                if(boxIsAllSame){
                                    //查询是否添加过
                                    long isAdd = boxListIsSeted.stream().filter(e->e.getId().equals(tccFbaBox.getId())).count();
                                    if(isAdd>0){
                                        logger.error("该箱子重复匹配:"+tccFbaBox.getId());
                                    }else {
                                        boxListIsSeted.add(tccFbaBox);
                                        //编辑关联信息
                                        logger.info("该箱子内商品已匹配:"+tccFbaBox.getId());
                                        storageMapper.updateFbaBoxDetailFbaId(tccFbaBoxUpInfo.getId(),tccFbaBox.getId(),box.getBoxId());
                                        sameNum++;
                                        //isAddByBox = true;
                                        break;
                                    }
                                }
                            }
                            if(sameNum==0){
                                logger.error("未匹配到FBA："+tccFbaBoxUpInfo.getFbaNo()+"对应箱子内的商品信息:"+box);
                                return R.error("未匹配到FBA："+tccFbaBoxUpInfo.getFbaNo()+"对应箱子内的商品信息");
                            }
                        }else {
                            logger.error("未匹配到FBA："+tccFbaBoxUpInfo.getFbaNo()+"对应箱子的尺寸:"+box);
                            //isSame = false;
                            return R.error("未匹配到FBA："+tccFbaBoxUpInfo.getFbaNo()+"对应箱子的尺寸信息");
                        }

                    }
                }else {
                    return R.error("装箱信息未获取到，请重试");
                }
            }

            return R.ok();
        }catch (ApiException e){
            logger.error("reSearchShipments - api失败原因如下:" + e.getResponseBody(), e.getResponseBody(),e);
            return R.error(e.getResponseBody());
        }catch (Exception e){
            logger.error("reSearchShipments - api失败原因如下:" + e.getMessage(), e.getMessage(),e);
            return R.error(e.getMessage());
        }


    }

    /**
     *    上传追踪编号
     * @param tccFbaPlan
     * @return
     */
    @Override
    public void updateShipmentTrackingDetails(TccFbaPlan tccFbaPlan) {
        try {
            //获取店铺信息
            JSONObject tpAmazonShop = getTpAmazonShop(tccFbaPlan.getShopId());
            if (tpAmazonShop == null) {
                logger.error("网店信息不存在");
                return;
            }
            FbaInboundApi fbaInboundApi = getFbaInboundApi(tpAmazonShop);
            if (fbaInboundApi == null) {
                logger.error("亚马逊token不存在");
                return;
            }

            //发货fba信息
            List<TccFbaDeliverItem> tccFbaDeliverItemList = new TccFbaDeliverItem().setFbaPlanBid(tccFbaPlan.getBid()).where("A.ApiTrackStatus != 2 AND A.ApiTrackStatus != 3").queryList();
            List<TccFbaDeliverItem> tccFbaDeliverItemListNew;

            //查询未上传追踪编码的
            List<TccFbaDeliverSon> tccFbaDeliverSonList = new TccFbaDeliverSon().setFbaPlanBid(tccFbaPlan.getBid()).queryList();
            List<TccFbaDeliverSon> tccFbaDeliverSonListNew;

            List<TccFbaBoxUpInfo> tccFbaBoxUpInfoList = new TccFbaBoxUpInfo().setBidFbaPlan(tccFbaPlan.getBid()).queryList();
            for (TccFbaBoxUpInfo tccFbaBoxUpInfo : tccFbaBoxUpInfoList) {

                TrackingDetailsInput trackingDetailsInput = new TrackingDetailsInput();
                tccFbaDeliverItemListNew = tccFbaDeliverItemList.stream().filter(e -> e.getFbaBoxUpInfoId().equals(tccFbaBoxUpInfo.getId())).collect(Collectors.toList());
                if (tccFbaDeliverItemListNew.size() != 0) {
                    TccFbaDeliverItem tccFbaDeliverItem = tccFbaDeliverItemListNew.get(0);
                    tccFbaDeliverSonListNew = tccFbaDeliverSonList.stream().filter(e -> e.getFbaDeliverItemId().equals(tccFbaDeliverItem.getId())).collect(Collectors.toList());

                    if (tccFbaDeliverSonListNew.size() != 0) {

                        SpdTrackingDetailInput spdTrackingDetailInput = new SpdTrackingDetailInput();
                        List<SpdTrackingItemInput> spdTrackingItemInputList = new ArrayList<>();
                        for (TccFbaDeliverSon tccFbaDeliverSon : tccFbaDeliverSonListNew) {
                            SpdTrackingItemInput spdTrackingItemInput = new SpdTrackingItemInput();
                            spdTrackingItemInput.setBoxId(tccFbaDeliverSon.getBoxNo());
                            spdTrackingItemInput.setTrackingId(tccFbaDeliverSon.getTransferno());
                            spdTrackingItemInputList.add(spdTrackingItemInput);
                        }
                        spdTrackingDetailInput.setSpdTrackingItems(spdTrackingItemInputList);

                        trackingDetailsInput.setSpdTrackingDetail(spdTrackingDetailInput);

                        UpdateShipmentTrackingDetailsRequest body = new UpdateShipmentTrackingDetailsRequest();
                        body.setTrackingDetails(trackingDetailsInput);
                        UpdateShipmentTrackingDetailsResponse updateShipmentTrackingDetailsResponse = null;
                        Boolean falx = true;
                        //等待1次调出循环
                        int h = 0;
                        while (falx) {
                            try {
                                logger.info("updateShipmentTrackingDetails开始id=" + tccFbaBoxUpInfo.getFbaId());
                                updateShipmentTrackingDetailsResponse = fbaInboundApi.updateShipmentTrackingDetails(
                                        tccFbaPlan.getInboundPlanId(),
                                        tccFbaBoxUpInfo.getFbaId(),
                                        body);
                                falx = false;
                                tccFbaDeliverItem.setApiTrackStatus(TccFbaDeliverEnum.ApiTrackStatus.YES.value);
                            } catch (ApiException e) {
                                if (e.getMessage().equals("java.net.SocketTimeoutException: timeout")) {
                                    logger.error("updateShipmentTrackingDetails超时继续请求," + tccFbaBoxUpInfo.getFbaId());
                                    Thread.sleep(1000L);
                                    if (h > 4){
                                        falx = false;
                                        tccFbaDeliverItem.setApiTrackStatus(TccFbaDeliverEnum.ApiTrackStatus.OVERTIME.value);
                                    }
                                    h = h + 1;
                                    continue;
                                }
                                tccFbaDeliverItem.setApiTrackStatus(TccFbaDeliverEnum.ApiTrackStatus.FAIL.value);
                                logger.error("updateShipmentTrackingDetails更新追踪失败原因如下:" + e.getResponseBody() + "id=" + tccFbaBoxUpInfo.getFbaId(), e.getResponseBody(), e);
                            }
                        }


                        logger.info("updateShipmentTrackingDetails成功!:" + JSONArray.toJSONString(updateShipmentTrackingDetailsResponse));
                        TccFbaInboundApiLog tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("updateShipmentTrackingDetails", tccFbaPlan.getId().toString(),
                                tccFbaBoxUpInfo.getFbaNo(),
                                JSONArray.toJSONString(body), JSONArray.toJSONString(updateShipmentTrackingDetailsResponse), 1);
                        tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);

                        R r = getInboundOperationStatusList(updateShipmentTrackingDetailsResponse.getOperationId(), fbaInboundApi);
                        if (r.getCode() != 0) {
                            tccFbaInboundApiLog = TccFbaInboundApiLog.tccFbaInboundApiLog("updateShipmentTrackingStatus", tccFbaPlan.getId().toString(),
                                    tccFbaBoxUpInfo.getFbaNo(),
                                    updateShipmentTrackingDetailsResponse.getOperationId(), r.getMsg(), 1);
                            tccFbaInboundApiLogMapper.insert(tccFbaInboundApiLog);
                            logger.error("updateShipmentTrackingDetails更新追踪失败原因如下:" + r.getMsg());
                        }

                        tccFbaDeliverItemMapper.update(tccFbaDeliverItem);
                    }
                }
            }
        }catch (Exception e){
            logger.error("updateShipmentTrackingDetails更新追踪失败原因如下:" + e.getMessage());
        }
        return ;
    }

    /**
     * 判断两个数组是否相同
     * @param arr
     * @param arr2
     * @return
     */
    public static boolean comarry(Set<String> arr,Set<String> arr2) {
        //首先比较两个数组长度，如果长度不相同，数组内容肯定不相同，返回false
        if (arr.size() != arr2.size()) {
            return false;
        }
        if (arr.containsAll(arr2)){
            return true;
        } else {
            return false;
        }
    }


}
